mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 00:52:33 -04:00
Compare commits
348 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a2e5d480c | ||
|
|
26e851ff7f | ||
|
|
89ec043ce1 | ||
|
|
98f0272a84 | ||
|
|
0933925a2b | ||
|
|
e92929fce4 | ||
|
|
f388412c48 | ||
|
|
836de7f1a5 | ||
|
|
43008aa42b | ||
|
|
7618d8301a | ||
|
|
09cfc979e4 | ||
|
|
00fc5541db | ||
|
|
954d06bdb7 | ||
|
|
12828ee4d4 | ||
|
|
c2e007a839 | ||
|
|
605bf3b9d3 | ||
|
|
ebd0333256 | ||
|
|
d7dcf192c7 | ||
|
|
2ad6f6e11f | ||
|
|
36a814b03e | ||
|
|
92bc99a805 | ||
|
|
b5ce207344 | ||
|
|
d04ff264fa | ||
|
|
9ad2b017e2 | ||
|
|
1fd5f5c893 | ||
|
|
43260891b7 | ||
|
|
aef0350346 | ||
|
|
83fbb0678c | ||
|
|
df3778c64f | ||
|
|
0dc09ea238 | ||
|
|
f085c3c98f | ||
|
|
8d4b1ba7d4 | ||
|
|
b3c543265d | ||
|
|
6eee404bb1 | ||
|
|
ec4226b5de | ||
|
|
8266a1490a | ||
|
|
56554710ea | ||
|
|
6a101e6260 | ||
|
|
f12038e63e | ||
|
|
ad2bf187bb | ||
|
|
4cbd97e409 | ||
|
|
e67c780afd | ||
|
|
0cbdeb7bf1 | ||
|
|
6be464ef84 | ||
|
|
54845a7627 | ||
|
|
2f6da0be7e | ||
|
|
cf87a5af3b | ||
|
|
207057c92d | ||
|
|
5300f180db | ||
|
|
ec7166eb00 | ||
|
|
36f041a1ff | ||
|
|
0dd2e9004d | ||
|
|
94f1c001f1 | ||
|
|
531a03562d | ||
|
|
3699f78e95 | ||
|
|
ebd2283b38 | ||
|
|
a7788570e5 | ||
|
|
2932ac9d86 | ||
|
|
888c211f44 | ||
|
|
61cf92ebdd | ||
|
|
80ec45e4f9 | ||
|
|
9e9851681f | ||
|
|
8394d4857c | ||
|
|
c700a017a0 | ||
|
|
c19eb94c52 | ||
|
|
597f24ca49 | ||
|
|
eb793b1601 | ||
|
|
07525c5b45 | ||
|
|
35df50c39d | ||
|
|
406ca20634 | ||
|
|
021e7861b8 | ||
|
|
5dfe4ef6f8 | ||
|
|
60a0fdc76b | ||
|
|
cd760454a5 | ||
|
|
c7144dbf96 | ||
|
|
c31e203104 | ||
|
|
6feefc5ce0 | ||
|
|
1d7f9e05ed | ||
|
|
6a858b29fd | ||
|
|
3f0e687558 | ||
|
|
ba412bc6cf | ||
|
|
31abcac4b4 | ||
|
|
d7f04ff6ee | ||
|
|
76fd81fad1 | ||
|
|
1cfcffc510 | ||
|
|
eaf9003ca2 | ||
|
|
751d6fe8a4 | ||
|
|
20ca6676d2 | ||
|
|
eded0f6c09 | ||
|
|
b5049651ad | ||
|
|
c95a6fe1e5 | ||
|
|
cd97c32444 | ||
|
|
70b204cb3f | ||
|
|
d2f1edfad8 | ||
|
|
2ddfcd5222 | ||
|
|
787ee411ce | ||
|
|
200d3577fa | ||
|
|
8ab99747f5 | ||
|
|
88f7c2041d | ||
|
|
43cb21329f | ||
|
|
b8a5f5fbf2 | ||
|
|
7ccd7b439f | ||
|
|
f0eceb03ed | ||
|
|
c2b9fc1a49 | ||
|
|
4d3a555b53 | ||
|
|
e35ab97b7e | ||
|
|
f9793e870f | ||
|
|
e48fedd526 | ||
|
|
b899ed3d64 | ||
|
|
e4adb881cb | ||
|
|
aa2450fae1 | ||
|
|
d9245566f5 | ||
|
|
16cc695115 | ||
|
|
f0e5ce7fd1 | ||
|
|
ea721d380b | ||
|
|
e193b6d870 | ||
|
|
766fc92a3b | ||
|
|
df6f2abfbe | ||
|
|
684245f24d | ||
|
|
01b081d809 | ||
|
|
a34d8852b6 | ||
|
|
18b6d48944 | ||
|
|
f3fa09fc91 | ||
|
|
cb2d8b4ba6 | ||
|
|
a9da370c0b | ||
|
|
b5620cb794 | ||
|
|
cf62e07bec | ||
|
|
ec4526b5f4 | ||
|
|
806f50eee3 | ||
|
|
6956eadaad | ||
|
|
9542c1d63c | ||
|
|
81bb02afb7 | ||
|
|
b8abf806ca | ||
|
|
0d10f5ba65 | ||
|
|
89409d0577 | ||
|
|
144283ca1c | ||
|
|
c56e2953cf | ||
|
|
e1d40348ce | ||
|
|
4def370980 | ||
|
|
54df52675b | ||
|
|
12ebdf27c0 | ||
|
|
de0f7ea5d4 | ||
|
|
72151bc123 | ||
|
|
8889abd5a4 | ||
|
|
7f7dcd2f33 | ||
|
|
95c3b1696e | ||
|
|
87cd1f87f4 | ||
|
|
21c4976a3a | ||
|
|
ec91e51142 | ||
|
|
f1c798e9ac | ||
|
|
f6996f4999 | ||
|
|
9ac5504377 | ||
|
|
91f3c722d6 | ||
|
|
31cf2c688c | ||
|
|
81d3ba5151 | ||
|
|
19daadbfd7 | ||
|
|
0acb371f62 | ||
|
|
18d990a034 | ||
|
|
85b6e352d4 | ||
|
|
c389aee112 | ||
|
|
725e57a27a | ||
|
|
9aab47de07 | ||
|
|
e6a6723d1f | ||
|
|
6e7c7771bd | ||
|
|
c609fc71bd | ||
|
|
b50f1657c3 | ||
|
|
bc1cc65ff2 | ||
|
|
697e59f9a4 | ||
|
|
61d6239c68 | ||
|
|
eba69f85c7 | ||
|
|
19b96e37fb | ||
|
|
14186f5c18 | ||
|
|
44593a3c8d | ||
|
|
4964a32c55 | ||
|
|
3d4ad94dcc | ||
|
|
6d5f98072d | ||
|
|
1a15c775f8 | ||
|
|
2d716b74b9 | ||
|
|
cc9fd4f4a4 | ||
|
|
43c5b72317 | ||
|
|
2856ea6370 | ||
|
|
67d65d878d | ||
|
|
e19bb63857 | ||
|
|
dbc5e54a92 | ||
|
|
b8913335b1 | ||
|
|
872ac8846e | ||
|
|
8c16171855 | ||
|
|
2e47ef38a9 | ||
|
|
81b4d919e5 | ||
|
|
f6d88f20f3 | ||
|
|
598c3aa336 | ||
|
|
ccefb99cbe | ||
|
|
35ce7dbeab | ||
|
|
74610aca6f | ||
|
|
02d4c5ac90 | ||
|
|
7f35dda5cc | ||
|
|
13355d42f7 | ||
|
|
77e82d7475 | ||
|
|
da2df4eb55 | ||
|
|
62fbdf3f63 | ||
|
|
554745a25a | ||
|
|
e12c0ca3dc | ||
|
|
a18e297a26 | ||
|
|
2d82e1bd6b | ||
|
|
7476d8dccc | ||
|
|
04b96e2cdc | ||
|
|
7375824ed4 | ||
|
|
06d47deef8 | ||
|
|
85d000e792 | ||
|
|
3ac27d8004 | ||
|
|
854a6e3787 | ||
|
|
a36dd5a8b9 | ||
|
|
7c620cbe24 | ||
|
|
7472b96c95 | ||
|
|
3ba42d3dcf | ||
|
|
eb3a40b07a | ||
|
|
f0cce1c902 | ||
|
|
9f26b7aa9c | ||
|
|
febf766be0 | ||
|
|
35d9fd4860 | ||
|
|
4581abb6d1 | ||
|
|
8d3c5114ba | ||
|
|
80b6954c29 | ||
|
|
da37548e2e | ||
|
|
c658bbca24 | ||
|
|
3b9a9db664 | ||
|
|
4e921cfdcf | ||
|
|
bd24224b76 | ||
|
|
a5ac388889 | ||
|
|
4be123dc84 | ||
|
|
becb898a51 | ||
|
|
268464ccde | ||
|
|
57aa96c412 | ||
|
|
cb74de7472 | ||
|
|
d35849c418 | ||
|
|
a9a112e063 | ||
|
|
1e87fe6b49 | ||
|
|
ed64eba13a | ||
|
|
0fbd0ca416 | ||
|
|
0a31267b1b | ||
|
|
97c7b010ed | ||
|
|
b6d30f6734 | ||
|
|
b9e1c38773 | ||
|
|
22d769ecae | ||
|
|
45ecd1b127 | ||
|
|
3f053611bd | ||
|
|
1582b8bc96 | ||
|
|
432e7e9714 | ||
|
|
31e237729c | ||
|
|
d2b03f6a9b | ||
|
|
51fe5ec982 | ||
|
|
ce9b01ce84 | ||
|
|
024b489af9 | ||
|
|
f980c2e3de | ||
|
|
db0e1c9f31 | ||
|
|
260c518562 | ||
|
|
689603de82 | ||
|
|
b51049227f | ||
|
|
0a86efc631 | ||
|
|
f8467845d2 | ||
|
|
9098bb431c | ||
|
|
86ed4f4f99 | ||
|
|
7795224e70 | ||
|
|
b729cee9e4 | ||
|
|
15bc5c64f3 | ||
|
|
440a132c6b | ||
|
|
f8447521a8 | ||
|
|
c8050ea865 | ||
|
|
11d831e4d7 | ||
|
|
15faf01ec9 | ||
|
|
7ee495624e | ||
|
|
45cc2d7bd8 | ||
|
|
15b45af550 | ||
|
|
91ebfbc215 | ||
|
|
ee40cb337a | ||
|
|
bdae290ec4 | ||
|
|
53c3d0d53d | ||
|
|
ed981ec8e8 | ||
|
|
723d757091 | ||
|
|
92ada6eb98 | ||
|
|
975d8ef0c7 | ||
|
|
65e9ff357b | ||
|
|
66495e6838 | ||
|
|
efe65e1ba8 | ||
|
|
6b500ee3e1 | ||
|
|
1ad6308f97 | ||
|
|
5d82bf946e | ||
|
|
c8fe56e57d | ||
|
|
88b6353465 | ||
|
|
4afddabe15 | ||
|
|
360ae9080e | ||
|
|
956aec1448 | ||
|
|
4bcd093bef | ||
|
|
f62b294a72 | ||
|
|
c2adf1dcd1 | ||
|
|
0932d2a0a6 | ||
|
|
e451284256 | ||
|
|
49f12695cf | ||
|
|
8d26961639 | ||
|
|
c9ec5043b9 | ||
|
|
03bfb8a46f | ||
|
|
0c5a7ab19b | ||
|
|
1561e4a89c | ||
|
|
b09cbb72fb | ||
|
|
d57f4a9527 | ||
|
|
0e015d52a5 | ||
|
|
7e0416ac97 | ||
|
|
98112497ba | ||
|
|
f952d65cfd | ||
|
|
182dec3e57 | ||
|
|
8ab6076566 | ||
|
|
6506cab55b | ||
|
|
fe638c88e0 | ||
|
|
cf7f380568 | ||
|
|
7e36727ce6 | ||
|
|
c29261487c | ||
|
|
c3229643d0 | ||
|
|
2b03e51bfc | ||
|
|
4cc72db463 | ||
|
|
d434490bdf | ||
|
|
2c15efbf48 | ||
|
|
c26dede97f | ||
|
|
1d899d387e | ||
|
|
ea3390d626 | ||
|
|
a04ded9cca | ||
|
|
f4ecc0dfb9 | ||
|
|
111ae9812c | ||
|
|
ba73845bad | ||
|
|
7ece28b981 | ||
|
|
5799a073fe | ||
|
|
85b1bc7929 | ||
|
|
de36172af3 | ||
|
|
f5fba51f5c | ||
|
|
a2185c7886 | ||
|
|
fae5515350 | ||
|
|
68d5969d33 | ||
|
|
3773bceb46 | ||
|
|
4ecb4189b8 | ||
|
|
d0d6170a71 | ||
|
|
cd98e75a42 | ||
|
|
3f031399cb | ||
|
|
0a16674f6e | ||
|
|
9365b8691e | ||
|
|
33825ba0b4 | ||
|
|
67db1c6e9b | ||
|
|
abdf6f40a2 | ||
|
|
523765b968 | ||
|
|
78f150cfbc |
44
CHANGELOG
44
CHANGELOG
@@ -1,3 +1,47 @@
|
||||
Hubzilla 5.6 (2021-05-11)
|
||||
- Improve postgres hubloc queries
|
||||
- Implement automatic duplicate singleton hubloc removal
|
||||
- Send author id, id_sig and key fields along with author/owner
|
||||
- Implement custom redis session backend
|
||||
- Improved registration workflow
|
||||
- Complete rewrite of the registration backend with many new features
|
||||
- Complete rewrite of the invite app
|
||||
- Update Spanish, Russian and Polish translations
|
||||
- Improved PHP8 compatibiliy (work in progress)
|
||||
|
||||
Bugfixes
|
||||
- Fix manual fetching of non-ascii domains
|
||||
- Fix revision not compared when importing items
|
||||
- Fix events not transformed to UTC when importing calendar
|
||||
- Fix timezone issue in mod cal
|
||||
- Fix profile photos not revalidated
|
||||
- Fix regression in caldav/carddav discovery
|
||||
- Fix caldav/carddav sync on remote access
|
||||
- Fix info and notice messages not bootstraped when using SSE
|
||||
- Fix URL including an @ treated like a webbie
|
||||
- Fix cover photo image issues on some mobile devices
|
||||
|
||||
Addons
|
||||
- Diaspora: improve performance when delivering public items
|
||||
- Diaspora: make sure to not process same contact more than once
|
||||
- Pubcrawl: make sure to not process same contact more than once
|
||||
- Pubcrawl: do not relay Like and Dislike activity
|
||||
- Pubcrawl: deprecate as_follow() in favour of core Activity::follow()
|
||||
- Pubcrawl: improved compatibility with mobilizon and xwiki
|
||||
- Pubcrawl: do not process follow/unfollw thread in as_create_note()
|
||||
- Diaspora: do not relay comments/likes of strangers if the thread-owner is local and does not allow comments/likes by strangers in the diaspora app settings
|
||||
|
||||
|
||||
Hubzilla 5.4.3 (2021-04-20)
|
||||
- Fix regression in mod notifications (only the last was visible)
|
||||
- Set Permissions-Policy: interest-cohort=() header by default
|
||||
- Fix xchans containing a % breaking get_forum_channels()
|
||||
- Fix webfinger if using a reverse proxy
|
||||
- Fix regression finding bookmarks
|
||||
- Fix zot6 hublocs import on channel import
|
||||
- Fix revision not checked in import_items()
|
||||
|
||||
|
||||
Hubzilla 5.4.2 (2021-03-15)
|
||||
- Fix translation plural variable
|
||||
- Fix issue with following/unfollowing a thread
|
||||
|
||||
48
CHANGELOG.air
Normal file
48
CHANGELOG.air
Normal file
@@ -0,0 +1,48 @@
|
||||
"air" is a branch name for revision of Account-Invite-Register at the Hubzilla project
|
||||
|
||||
Invite:
|
||||
* Rewritten and now language template driven
|
||||
* Selectable templates for the invite mails
|
||||
* Invitor may add personal notes in the mailtext
|
||||
+ Invite codes are bound to the recipients email address
|
||||
* Invite mod never more creates accounts
|
||||
* new db scheme for table register
|
||||
* existing register table will be migrated to the new schema even when detected at runtime
|
||||
* Bugfix: creating invite codes when admin only calls Invite w/o any further action
|
||||
* account library revision also together with invite mod
|
||||
* Depending on config: Users may send invitations also
|
||||
* Invitations expires, controlled by the invitor
|
||||
* Changed and new configs:
|
||||
* * invitation_only As usual before
|
||||
* * invitation_also Beside other registration policies, invitations may be used also
|
||||
* * invitation_max_per_day defaults 50, may be changed in adminUI admin>site
|
||||
* * invitation_max_per_user defaults 4
|
||||
* Requirements:
|
||||
* * Addon language has to be installed
|
||||
|
||||
Register:
|
||||
* Register panel (form) and js interaction changed
|
||||
* Unused registrations expire
|
||||
* Depending on config, anonymous registrations (w/o email) are supported
|
||||
* :... dont't panic, that may let grow security
|
||||
* Even anonymous users have to confirm their registration
|
||||
* Registrations may be enabled / disabled time driven for each day in the week (dudy)
|
||||
* Unsoliced registration floods may be blocked
|
||||
* Limited registrations from one single source ip
|
||||
* Using one additional log file, to easy interfare with f2b
|
||||
|
||||
Account:
|
||||
* An user account always becomes created only if all depending conditions are satisfied
|
||||
* AdminUI for site configuration, accounts and registrations enhancements
|
||||
* Still untouched, but accountUI needs enhanced async control in case for mass delete
|
||||
with deep level of recursion cascade of the dependencies (channels etc). An open TODO
|
||||
since years for instances with many much users and channels.
|
||||
|
||||
History:
|
||||
2020.03 Hubzilla Prod version 4.6 (master branch) of hubzilla/core was the base for AIR
|
||||
that was assigned Version 4.6.2 at sn/core
|
||||
2021.02 Hubzilla Prod version 5.2.1 (master branch) of hubzilla/core was new base for AIR
|
||||
that was assigned version 5.2.2 at sn/core (air.5)
|
||||
plus adjustment of hubzilla 5.2.2 (master) to sn/core (air.5) version 5.2.9
|
||||
|
||||
|
||||
@@ -55,11 +55,13 @@ class Cron {
|
||||
db_utcnow()
|
||||
);
|
||||
|
||||
remove_expired_registrations();
|
||||
|
||||
$interval = get_config('system', 'delivery_interval', 3);
|
||||
|
||||
// expire any expired items
|
||||
|
||||
$r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
|
||||
$r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
|
||||
and item_deleted = 0 ",
|
||||
db_utcnow()
|
||||
);
|
||||
@@ -131,7 +133,7 @@ class Cron {
|
||||
|
||||
// publish any applicable items that were set to be published in the future
|
||||
// (time travel posts). Restrict to items that have come of age in the last
|
||||
// couple of days to limit the query to something reasonable.
|
||||
// couple of days to limit the query to something reasonable.
|
||||
|
||||
$r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
|
||||
db_utcnow(),
|
||||
@@ -192,7 +194,7 @@ class Cron {
|
||||
// update any photos which didn't get imported properly
|
||||
// This should be rare
|
||||
|
||||
$r = q("select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = ''
|
||||
$r = q("select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = ''
|
||||
and xchan_photo_date < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 DAY')
|
||||
@@ -238,7 +240,7 @@ class Cron {
|
||||
|
||||
set_config('system', 'lastcron', datetime_convert());
|
||||
|
||||
//All done - clear the lockfile
|
||||
//All done - clear the lockfile
|
||||
@unlink($lockfile);
|
||||
|
||||
return;
|
||||
|
||||
@@ -93,6 +93,7 @@ class Cron_daily {
|
||||
Master::Summon(array('Cli_suggest'));
|
||||
|
||||
remove_obsolete_hublocs();
|
||||
remove_duplicate_singleton_hublocs();
|
||||
|
||||
z6_discover();
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class Queue {
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$h = parse_url($rr['outq_posturl']);
|
||||
$desturl = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
|
||||
$desturl = $h['scheme'] . '://' . $h['host'] . (isset($h['port']) ? ':' . $h['port'] : '');
|
||||
q("update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - INTERVAL %s",
|
||||
dbesc($desturl),
|
||||
db_utcnow(), db_quoteinterval('1 MONTH')
|
||||
|
||||
@@ -104,7 +104,10 @@ class Activity {
|
||||
if ($x['success']) {
|
||||
$m = parse_url($url);
|
||||
if ($m) {
|
||||
$site_url = unparse_url(['scheme' => $m['scheme'], 'host' => $m['host'], 'port' => $m['port'] ]);
|
||||
$y = [ 'scheme' => $m['scheme'], 'host' => $m['host'] ];
|
||||
if (array_key_exists('port', $m))
|
||||
$y['port'] = $m['port'];
|
||||
$site_url = unparse_url($y);
|
||||
q("UPDATE site SET site_update = '%s', site_dead = 0 WHERE site_url = '%s' AND site_update < %s - INTERVAL %s",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($site_url),
|
||||
@@ -129,8 +132,8 @@ class Activity {
|
||||
}
|
||||
|
||||
static function fetch_profile($x) {
|
||||
$r = q("select * from xchan where xchan_url like '%s' limit 1",
|
||||
dbesc($x['id'] . '/%')
|
||||
$r = q("select * from xchan where xchan_url = '%s' limit 1",
|
||||
dbesc($x['id'])
|
||||
);
|
||||
if (!$r) {
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
@@ -572,7 +575,7 @@ class Activity {
|
||||
|
||||
$ret = [];
|
||||
|
||||
if ($item['tag'] && is_array($item['tag'])) {
|
||||
if (array_key_exists('tag', $item) && is_array($item['tag'])) {
|
||||
$ptr = $item['tag'];
|
||||
if (!array_key_exists(0, $ptr)) {
|
||||
$ptr = [$ptr];
|
||||
@@ -581,23 +584,25 @@ class Activity {
|
||||
if (!array_key_exists('type', $t))
|
||||
$t['type'] = 'Hashtag';
|
||||
|
||||
switch ($t['type']) {
|
||||
case 'Hashtag':
|
||||
$ret[] = ['ttype' => TERM_HASHTAG, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '#') ? substr($t['name'], 1) : $t['name'])];
|
||||
break;
|
||||
if (array_key_exists('href', $t) && array_key_exists('name', $t)) {
|
||||
switch ($t['type']) {
|
||||
case 'Hashtag':
|
||||
$ret[] = ['ttype' => TERM_HASHTAG, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '#') ? substr($t['name'], 1) : $t['name'])];
|
||||
break;
|
||||
|
||||
case 'Mention':
|
||||
$mention_type = substr($t['name'], 0, 1);
|
||||
if ($mention_type === '!') {
|
||||
$ret[] = ['ttype' => TERM_FORUM, 'url' => $t['href'], 'term' => escape_tags(substr($t['name'], 1))];
|
||||
}
|
||||
else {
|
||||
$ret[] = ['ttype' => TERM_MENTION, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '@') ? substr($t['name'], 1) : $t['name'])];
|
||||
}
|
||||
break;
|
||||
case 'Mention':
|
||||
$mention_type = substr($t['name'], 0, 1);
|
||||
if ($mention_type === '!') {
|
||||
$ret[] = ['ttype' => TERM_FORUM, 'url' => $t['href'], 'term' => escape_tags(substr($t['name'], 1))];
|
||||
}
|
||||
else {
|
||||
$ret[] = ['ttype' => TERM_MENTION, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '@') ? substr($t['name'], 1) : $t['name'])];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -609,7 +614,7 @@ class Activity {
|
||||
|
||||
$ret = [];
|
||||
|
||||
if ($item['term']) {
|
||||
if (array_key_exists('term', $item) && is_array($item['term'])) {
|
||||
foreach ($item['term'] as $t) {
|
||||
switch ($t['ttype']) {
|
||||
case TERM_HASHTAG:
|
||||
@@ -640,7 +645,7 @@ class Activity {
|
||||
|
||||
$ret = [];
|
||||
|
||||
if ($item['attach']) {
|
||||
if (array_key_exists('attach', $item)) {
|
||||
$atts = ((is_array($item['attach'])) ? $item['attach'] : json_decode($item['attach'], true));
|
||||
if ($atts) {
|
||||
foreach ($atts as $att) {
|
||||
@@ -653,7 +658,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($item['iconfig']) {
|
||||
if (array_key_exists('iconfig', $item) && is_array($item['iconfig'])) {
|
||||
foreach ($item['iconfig'] as $att) {
|
||||
if ($att['sharing']) {
|
||||
$value = ((is_string($att['v']) && preg_match('|^a:[0-9]+:{.*}$|s', $att['v'])) ? unserialize($att['v']) : $att['v']);
|
||||
@@ -697,16 +702,16 @@ class Activity {
|
||||
|
||||
$ret = [];
|
||||
|
||||
if ($item['attachment']) {
|
||||
if (array_key_exists('attachment', $item) && is_array($item['attachment'])) {
|
||||
foreach ($item['attachment'] as $att) {
|
||||
$entry = [];
|
||||
if ($att['href'])
|
||||
if (array_key_exists('href', $att))
|
||||
$entry['href'] = $att['href'];
|
||||
elseif ($att['url'])
|
||||
elseif (array_key_exists('url', $att))
|
||||
$entry['href'] = $att['url'];
|
||||
if ($att['mediaType'])
|
||||
if (array_key_exists('mediaType', $att))
|
||||
$entry['type'] = $att['mediaType'];
|
||||
elseif ($att['type'] === 'Image')
|
||||
elseif (array_key_exists('type', $att) && $att['type'] === 'Image')
|
||||
$entry['type'] = 'image/jpeg';
|
||||
if ($entry)
|
||||
$ret[] = $entry;
|
||||
@@ -978,19 +983,17 @@ 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']) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($i['term'] as $t) {
|
||||
if (!$t['url']) {
|
||||
continue;
|
||||
}
|
||||
if ($t['ttype'] == TERM_MENTION) {
|
||||
$url = self::lookup_term_url($t['url']);
|
||||
$list[] = (($url) ? $url : $t['url']);
|
||||
if (array_key_exists('term', $i) && is_array($i['term'])) {
|
||||
foreach ($i['term'] as $t) {
|
||||
if (!$t['url']) {
|
||||
continue;
|
||||
}
|
||||
if ($t['ttype'] == TERM_MENTION) {
|
||||
$url = self::lookup_term_url($t['url']);
|
||||
$list[] = (($url) ? $url : $t['url']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1091,18 +1094,7 @@ class Activity {
|
||||
'height' => 300,
|
||||
'width' => 300,
|
||||
];
|
||||
$ret['url'] = [
|
||||
[
|
||||
'type' => 'Link',
|
||||
'mediaType' => 'text/html',
|
||||
'href' => $p['xchan_url']
|
||||
],
|
||||
[
|
||||
'type' => 'Link',
|
||||
'mediaType' => 'text/x-zot+json',
|
||||
'href' => $p['xchan_url']
|
||||
]
|
||||
];
|
||||
$ret['url'] = $p['xchan_url'];
|
||||
|
||||
$ret['publicKey'] = [
|
||||
'id' => $p['xchan_url'],
|
||||
@@ -1331,12 +1323,12 @@ class Activity {
|
||||
*
|
||||
*/
|
||||
|
||||
$person_obj = $act->actor;
|
||||
|
||||
if ($act->type === 'Follow') {
|
||||
if (in_array($act->type, [ 'Follow', 'Invite', 'Join'])) {
|
||||
$their_follow_id = $act->id;
|
||||
}
|
||||
|
||||
$person_obj = (($act->type == 'Invite') ? $act->obj : $act->actor);
|
||||
|
||||
if (is_array($person_obj)) {
|
||||
|
||||
// store their xchan and hubloc
|
||||
@@ -1354,9 +1346,8 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
$x = PermissionRoles::role_perms('social');
|
||||
$p = Permissions::FilledPerms($x['perms_connect']);
|
||||
$their_perms = Permissions::serialise($p);
|
||||
$x = \Zotlabs\Access\PermissionRoles::role_perms('social');
|
||||
$their_perms = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']);
|
||||
|
||||
if ($contact && $contact['abook_id']) {
|
||||
|
||||
@@ -1365,18 +1356,18 @@ class Activity {
|
||||
switch ($act->type) {
|
||||
|
||||
case 'Follow':
|
||||
case 'Invite':
|
||||
case 'Join':
|
||||
|
||||
// A second Follow request, but we haven't approved the first one
|
||||
|
||||
if ($contact['abook_pending']) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We've already approved them or followed them first
|
||||
// Send an Accept back to them
|
||||
|
||||
set_abconfig($channel['channel_id'], $person_obj['id'], 'pubcrawl', 'their_follow_id', $their_follow_id);
|
||||
Master::Summon(['Notifier', 'permissions_accept', $contact['abook_id']]);
|
||||
Master::Summon(['Notifier', 'permission_accept', $contact['abook_id']]);
|
||||
return;
|
||||
|
||||
case 'Accept':
|
||||
@@ -1430,8 +1421,8 @@ class Activity {
|
||||
}
|
||||
$ret = $r[0];
|
||||
|
||||
$p = Permissions::connect_perms($channel['channel_id']);
|
||||
$my_perms = Permissions::serialise($p['perms']);
|
||||
$p = \Zotlabs\Access\Permissions::connect_perms($channel['channel_id']);
|
||||
$my_perms = $p['perms'];
|
||||
$automatic = $p['automatic'];
|
||||
|
||||
$closeness = get_pconfig($channel['channel_id'], 'system', 'new_abook_closeness', 80);
|
||||
@@ -1451,12 +1442,13 @@ class Activity {
|
||||
]
|
||||
);
|
||||
|
||||
if ($my_perms)
|
||||
set_abconfig($channel['channel_id'], $ret['xchan_hash'], 'system', 'my_perms', $my_perms);
|
||||
|
||||
if ($their_perms)
|
||||
set_abconfig($channel['channel_id'], $ret['xchan_hash'], 'system', 'their_perms', $their_perms);
|
||||
if($my_perms)
|
||||
foreach($my_perms as $k => $v)
|
||||
set_abconfig($channel['channel_id'],$ret['xchan_hash'],'my_perms',$k,$v);
|
||||
|
||||
if($their_perms)
|
||||
foreach($their_perms as $k => $v)
|
||||
set_abconfig($channel['channel_id'],$ret['xchan_hash'],'their_perms',$k,$v);
|
||||
|
||||
if ($r) {
|
||||
logger("New ActivityPub follower for {$channel['channel_name']}");
|
||||
@@ -1477,9 +1469,9 @@ class Activity {
|
||||
|
||||
if ($my_perms && $automatic) {
|
||||
// send an Accept for this Follow activity
|
||||
Master::Summon(['Notifier', 'permissions_accept', $new_connection[0]['abook_id']]);
|
||||
Master::Summon(['Notifier', 'permission_accept', $new_connection[0]['abook_id']]);
|
||||
// Send back a Follow notification to them
|
||||
Master::Summon(['Notifier', 'permissions_create', $new_connection[0]['abook_id']]);
|
||||
Master::Summon(['Notifier', 'permission_create', $new_connection[0]['abook_id']]);
|
||||
}
|
||||
|
||||
$clone = [];
|
||||
@@ -1604,13 +1596,13 @@ class Activity {
|
||||
|
||||
if ($inbox) {
|
||||
$collections['inbox'] = $inbox;
|
||||
if ($person_obj['outbox'])
|
||||
if (array_key_exists('outbox', $person_obj))
|
||||
$collections['outbox'] = $person_obj['outbox'];
|
||||
if ($person_obj['followers'])
|
||||
if (array_key_exists('followers', $person_obj))
|
||||
$collections['followers'] = $person_obj['followers'];
|
||||
if ($person_obj['following'])
|
||||
if (array_key_exists('following', $person_obj))
|
||||
$collections['following'] = $person_obj['following'];
|
||||
if ($person_obj['endpoints'] && $person_obj['endpoints']['sharedInbox'])
|
||||
if (array_key_exists('endpoints', $person_obj) && array_key_exists('sharedInbox', $person_obj['endpoints']))
|
||||
$collections['sharedInbox'] = $person_obj['endpoints']['sharedInbox'];
|
||||
}
|
||||
|
||||
@@ -2123,22 +2115,22 @@ class Activity {
|
||||
$s['uuid'] = $act->obj['diaspora:guid'];
|
||||
$s['parent_mid'] = $act->parent_id;
|
||||
|
||||
if ($act->data['published']) {
|
||||
if (array_key_exists('published', $act->data)) {
|
||||
$s['created'] = datetime_convert('UTC', 'UTC', $act->data['published']);
|
||||
}
|
||||
elseif ($act->obj['published']) {
|
||||
elseif (array_key_exists('published', $act->obj)) {
|
||||
$s['created'] = datetime_convert('UTC', 'UTC', $act->obj['published']);
|
||||
}
|
||||
if ($act->data['updated']) {
|
||||
if (array_key_exists('updated', $act->data)) {
|
||||
$s['edited'] = datetime_convert('UTC', 'UTC', $act->data['updated']);
|
||||
}
|
||||
elseif ($act->obj['updated']) {
|
||||
elseif (array_key_exists('updated', $act->obj)) {
|
||||
$s['edited'] = datetime_convert('UTC', 'UTC', $act->obj['updated']);
|
||||
}
|
||||
if ($act->data['expires']) {
|
||||
if (array_key_exists('expires', $act->data)) {
|
||||
$s['expires'] = datetime_convert('UTC', 'UTC', $act->data['expires']);
|
||||
}
|
||||
elseif ($act->obj['expires']) {
|
||||
elseif (array_key_exists('expires', $act->obj)) {
|
||||
$s['expires'] = datetime_convert('UTC', 'UTC', $act->obj['expires']);
|
||||
}
|
||||
|
||||
@@ -2198,10 +2190,10 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if (!$s['created'])
|
||||
if (! array_key_exists('created', $s))
|
||||
$s['created'] = datetime_convert();
|
||||
|
||||
if (!$s['edited'])
|
||||
if (! array_key_exists('edited', $s))
|
||||
$s['edited'] = $s['created'];
|
||||
|
||||
$s['title'] = (($response_activity) ? EMPTY_STR : self::bb_content($content, 'name'));
|
||||
@@ -2315,7 +2307,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if ($act->obj['closed']) {
|
||||
if (array_key_exists('closed', $act->obj)) {
|
||||
$s['comments_closed'] = datetime_convert('UTC', 'UTC', $act->obj['closed']);
|
||||
}
|
||||
|
||||
@@ -2731,7 +2723,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if ($act->obj['conversation']) {
|
||||
if (array_key_exists('conversation', $act->obj)) {
|
||||
set_iconfig($item, 'ostatus', 'conversation', $act->obj['conversation'], 1);
|
||||
}
|
||||
|
||||
@@ -3384,22 +3376,25 @@ class Activity {
|
||||
require_once('include/event.php');
|
||||
$ret = false;
|
||||
|
||||
if (is_array($content[$field])) {
|
||||
foreach ($content[$field] as $k => $v) {
|
||||
$ret .= html2bbcode($v);
|
||||
// save this for auto-translate or dynamic filtering
|
||||
// $ret .= '[language=' . $k . ']' . html2bbcode($v) . '[/language]';
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($field === 'bbcode' && array_key_exists('bbcode', $content)) {
|
||||
$ret = $content[$field];
|
||||
if (array_key_exists($field, $content)) {
|
||||
if (is_array($content[$field])) {
|
||||
foreach ($content[$field] as $k => $v) {
|
||||
$ret .= html2bbcode($v);
|
||||
// save this for auto-translate or dynamic filtering
|
||||
// $ret .= '[language=' . $k . ']' . html2bbcode($v) . '[/language]';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$ret = html2bbcode($content[$field]);
|
||||
if ($field === 'bbcode' && array_key_exists('bbcode', $content)) {
|
||||
$ret = $content[$field];
|
||||
}
|
||||
else {
|
||||
$ret = html2bbcode($content[$field]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($field === 'content' && $content['event'] && (!strpos($ret, '[event'))) {
|
||||
|
||||
if ($field === 'content' && array_key_exists('event', $content) && (!strpos($ret, '[event'))) {
|
||||
$ret .= format_event_bbcode($content['event']);
|
||||
}
|
||||
|
||||
|
||||
@@ -551,7 +551,7 @@ class Apps {
|
||||
'$app' => $papp,
|
||||
'$icon' => $icon,
|
||||
'$hosturl' => $hosturl,
|
||||
'$purchase' => (($papp['page'] && (! $installed)) ? t('Purchase') : ''),
|
||||
'$purchase' => ((isset($papp['page']) && (! $installed)) ? t('Purchase') : ''),
|
||||
'$installed' => $installed,
|
||||
'$action_label' => (($hosturl && in_array($mode, ['view','install'])) ? $install_action : ''),
|
||||
'$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''),
|
||||
@@ -559,8 +559,8 @@ class Apps {
|
||||
'$undelete' => ((local_channel() && $mode == 'edit') ? t('Undelete') : ''),
|
||||
'$settings_url' => ((local_channel() && $installed && $mode == 'list') ? $papp['settings_url'] : ''),
|
||||
'$deleted' => $papp['deleted'],
|
||||
'$feature' => (($papp['embed'] || $mode == 'edit') ? false : true),
|
||||
'$pin' => (($papp['embed'] || $mode == 'edit') ? false : true),
|
||||
'$feature' => ((isset($papp['embed']) || $mode == 'edit') ? false : true),
|
||||
'$pin' => ((isset($papp['embed']) || $mode == 'edit') ? false : true),
|
||||
'$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true),
|
||||
'$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true),
|
||||
'$navapps' => (($mode == 'nav') ? true : false),
|
||||
@@ -1276,58 +1276,58 @@ class Apps {
|
||||
|
||||
$ret['type'] = 'personal';
|
||||
|
||||
if($app['app_id'])
|
||||
if(!empty($app['app_id']))
|
||||
$ret['guid'] = $app['app_id'];
|
||||
|
||||
if($app['app_sig'])
|
||||
if(!empty($app['app_sig']))
|
||||
$ret['sig'] = $app['app_sig'];
|
||||
|
||||
if($app['app_author'])
|
||||
if(!empty($app['app_author']))
|
||||
$ret['author'] = $app['app_author'];
|
||||
|
||||
if($app['app_name'])
|
||||
if(!empty($app['app_name']))
|
||||
$ret['name'] = $app['app_name'];
|
||||
|
||||
if($app['app_desc'])
|
||||
if(!empty($app['app_desc']))
|
||||
$ret['desc'] = $app['app_desc'];
|
||||
|
||||
if($app['app_url'])
|
||||
if(!empty($app['app_url']))
|
||||
$ret['url'] = $app['app_url'];
|
||||
|
||||
if($app['app_photo'])
|
||||
if(!empty($app['app_photo']))
|
||||
$ret['photo'] = $app['app_photo'];
|
||||
|
||||
if($app['app_icon'])
|
||||
if(!empty($app['app_icon']))
|
||||
$ret['icon'] = $app['app_icon'];
|
||||
|
||||
if($app['app_version'])
|
||||
if(!empty($app['app_version']))
|
||||
$ret['version'] = $app['app_version'];
|
||||
|
||||
if($app['app_addr'])
|
||||
if(!empty($app['app_addr']))
|
||||
$ret['addr'] = $app['app_addr'];
|
||||
|
||||
if($app['app_price'])
|
||||
if(!empty($app['app_price']))
|
||||
$ret['price'] = $app['app_price'];
|
||||
|
||||
if($app['app_page'])
|
||||
if(!empty($app['app_page']))
|
||||
$ret['page'] = $app['app_page'];
|
||||
|
||||
if($app['app_requires'])
|
||||
if(!empty($app['app_requires']))
|
||||
$ret['requires'] = $app['app_requires'];
|
||||
|
||||
if($app['app_system'])
|
||||
if(!empty($app['app_system']))
|
||||
$ret['system'] = $app['app_system'];
|
||||
|
||||
if($app['app_options'])
|
||||
if(!empty($app['app_options']))
|
||||
$ret['options'] = $app['app_options'];
|
||||
|
||||
if($app['app_plugin'])
|
||||
if(!empty($app['app_plugin']))
|
||||
$ret['plugin'] = trim($app['app_plugin']);
|
||||
|
||||
if($app['app_deleted'])
|
||||
if(!empty($app['app_deleted']))
|
||||
$ret['deleted'] = $app['app_deleted'];
|
||||
|
||||
if($app['term']) {
|
||||
if(!empty($app['term']) && is_array($app['term'])) {
|
||||
$s = '';
|
||||
foreach($app['term'] as $t) {
|
||||
if($s)
|
||||
|
||||
@@ -207,13 +207,13 @@ class Connect {
|
||||
}
|
||||
|
||||
$my_perms = $p['perms'];
|
||||
|
||||
|
||||
$profile_assign = get_pconfig($uid,'system','profile_assign','');
|
||||
|
||||
|
||||
// See if we are already connected by virtue of having an abook record
|
||||
|
||||
$r = q("select abook_id, abook_xchan, abook_pending, abook_instance from abook
|
||||
$r = q("select abook_id, abook_xchan, abook_pending, abook_instance from abook
|
||||
where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($xchan_hash),
|
||||
intval($uid)
|
||||
@@ -282,7 +282,7 @@ class Connect {
|
||||
|
||||
// fetch the entire record
|
||||
|
||||
$r = q("select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash
|
||||
$r = q("select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash
|
||||
where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($xchan_hash),
|
||||
intval($uid)
|
||||
|
||||
@@ -978,12 +978,12 @@ class Enotify {
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/admin/accounts',
|
||||
'name' => $rr['account_email'],
|
||||
//'addr' => $rr['account_email'],
|
||||
'name' => $rr['reg_did2'],
|
||||
//'addr' => '',
|
||||
'photo' => z_root() . '/' . get_default_profile_photo(48),
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(),$rr['account_created']),
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(),$rr['reg_created']),
|
||||
'hclass' => ('notify-unseen'),
|
||||
'message' => t('requires approval')
|
||||
'message' => t('status verified')
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
@@ -716,6 +716,9 @@ class Libsync {
|
||||
dbesc($sender['hash'])
|
||||
);
|
||||
|
||||
if(!$xisting)
|
||||
$xisting = [];
|
||||
|
||||
// See if a primary is specified
|
||||
|
||||
$has_primary = false;
|
||||
@@ -781,7 +784,7 @@ class Libsync {
|
||||
$t = datetime_convert('UTC', 'UTC', 'now - 15 minutes');
|
||||
|
||||
if (array_key_exists('site', $arr) && $location['url'] == $arr['site']['url']) {
|
||||
q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d and hubloc_connected < '%s'",
|
||||
q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d and hubloc_updated < '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['hubloc_id']),
|
||||
|
||||
@@ -299,7 +299,6 @@ class Libzot {
|
||||
}
|
||||
|
||||
$record = Zotfinger::exec($url, $channel);
|
||||
|
||||
// Check the HTTP signature
|
||||
|
||||
$hsig = $record['signature'];
|
||||
@@ -2665,9 +2664,9 @@ class Libzot {
|
||||
// we may only end up with one; which results in posts with no author name or photo and are a bit
|
||||
// of a hassle to repair. If either or both are missing, do a full discovery probe.
|
||||
|
||||
if (!array_key_exists('id', $x)) {
|
||||
return import_author_activitypub($x);
|
||||
}
|
||||
//if (!array_key_exists('id', $x)) {
|
||||
//return import_author_activitypub($x);
|
||||
//}
|
||||
|
||||
$hash = self::make_xchan_hash($x['id'], $x['key']);
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ class NativeWiki {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function update_wiki($channel_id, $observer_hash, $arr, $acl) {
|
||||
|
||||
$w = self::get_wiki($channel_id, $observer_hash, $arr['resource_id']);
|
||||
@@ -156,8 +157,8 @@ class NativeWiki {
|
||||
}
|
||||
}
|
||||
|
||||
public static function sync_a_wiki_item($uid,$id,$resource_id) {
|
||||
|
||||
public static function sync_a_wiki_item($uid,$id,$resource_id) {
|
||||
|
||||
$r = q("SELECT * from item WHERE uid = %d AND ( id = %d OR ( resource_type = '%s' and resource_id = '%s' )) ",
|
||||
intval($uid),
|
||||
@@ -165,8 +166,8 @@ class NativeWiki {
|
||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
|
||||
$q = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s'",
|
||||
dbesc($r[0]['resource_id'])
|
||||
);
|
||||
@@ -185,20 +186,27 @@ class NativeWiki {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function delete_wiki($channel_id,$observer_hash,$resource_id) {
|
||||
|
||||
$w = self::get_wiki($channel_id,$observer_hash,$resource_id);
|
||||
$item = $w['wiki'];
|
||||
if(! $item) {
|
||||
return array('item' => null, 'success' => false);
|
||||
}
|
||||
else {
|
||||
$drop = drop_item($item['id'], false, DROPITEM_NORMAL);
|
||||
if(! $w['wiki']) {
|
||||
return [ 'success' => false ];
|
||||
}
|
||||
else {
|
||||
|
||||
info( t('Wiki files deleted successfully'));
|
||||
$r = q("SELECT id FROM item WHERE uid = %s AND resource_id = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
return array('item' => $item, 'item_id' => $item['id'], 'success' => (($drop === 1) ? true : false));
|
||||
$ids = array_column($r, 'id');
|
||||
drop_items($ids, true, DROPITEM_PHASE1);
|
||||
|
||||
info(t('Wiki files deleted successfully'));
|
||||
|
||||
return [ 'success' => true ];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,13 +215,13 @@ class NativeWiki {
|
||||
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
|
||||
|
||||
$item = q("SELECT * FROM item WHERE uid = %d AND resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0
|
||||
$sql_extra limit 1",
|
||||
$sql_extra ORDER BY id LIMIT 1",
|
||||
intval($channel_id),
|
||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if(! $item) {
|
||||
return array('wiki' => null);
|
||||
return [ 'wiki' => null ];
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -259,6 +267,7 @@ class NativeWiki {
|
||||
|
||||
|
||||
public static function get_permissions($resource_id, $owner_id, $observer_hash) {
|
||||
|
||||
// TODO: For now, only the owner can edit
|
||||
$sql_extra = item_permissions_sql($owner_id, $observer_hash);
|
||||
|
||||
@@ -283,6 +292,7 @@ class NativeWiki {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function name_encode ($string) {
|
||||
|
||||
$string = html_entity_decode($string);
|
||||
@@ -298,6 +308,7 @@ class NativeWiki {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
public static function name_decode ($string) {
|
||||
|
||||
$encoding = mb_internal_encoding();
|
||||
|
||||
@@ -109,6 +109,7 @@ class NativeWikiPage {
|
||||
return [ 'success' => false, 'message' => t('Wiki page create failed.') ];
|
||||
}
|
||||
|
||||
|
||||
static public function rename_page($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
@@ -167,7 +168,9 @@ class NativeWikiPage {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public function get_page_content($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
@@ -198,7 +201,9 @@ class NativeWikiPage {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public function page_history($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
@@ -290,6 +295,7 @@ class NativeWikiPage {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static public function load_page_history($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
@@ -338,6 +344,7 @@ class NativeWikiPage {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static public function save_page($arr) {
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$content = ((array_key_exists('content',$arr)) ? $arr['content'] : '');
|
||||
@@ -389,14 +396,15 @@ class NativeWikiPage {
|
||||
return array('message' => t('Page update failed.'), 'success' => false);
|
||||
}
|
||||
|
||||
|
||||
static public function delete_page($arr) {
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
|
||||
|
||||
$pageUrlName = (array_key_exists('pageUrlName',$arr) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = (array_key_exists('resource_id',$arr) ? $arr['resource_id'] : '');
|
||||
$observer_hash = (array_key_exists('observer_hash',$arr) ? $arr['observer_hash'] : '');
|
||||
$channel_id = (array_key_exists('channel_id',$arr) ? $arr['channel_id'] : 0);
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
|
||||
if(! $w['wiki']) {
|
||||
return [ 'success' => false, 'message' => t('Error reading wiki') ];
|
||||
}
|
||||
@@ -416,14 +424,16 @@ class NativeWikiPage {
|
||||
}
|
||||
|
||||
if($ids) {
|
||||
drop_items($ids);
|
||||
drop_items($ids, true, DROPITEM_PHASE1);
|
||||
return [ 'success' => true ];
|
||||
}
|
||||
|
||||
return [ 'success' => false, 'message' => t('Nothing deleted') ];
|
||||
}
|
||||
|
||||
|
||||
static public function revert_page($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$commitHash = ((array_key_exists('commitHash',$arr)) ? $arr['commitHash'] : null);
|
||||
@@ -454,7 +464,9 @@ class NativeWikiPage {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public function compare_page($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$currentCommit = ((array_key_exists('currentCommit',$arr)) ? $arr['currentCommit'] : (-1));
|
||||
@@ -490,6 +502,7 @@ class NativeWikiPage {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public function commit($arr) {
|
||||
|
||||
$commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : t('Page updated'));
|
||||
@@ -570,7 +583,6 @@ class NativeWikiPage {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Replace the instances of the string [toc] with a list element that will be populated by
|
||||
* a table of contents by the JavaScript library
|
||||
@@ -586,6 +598,7 @@ class NativeWikiPage {
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a select set of bbcode tags. Much of the code is copied from include/bbcode.php
|
||||
* @param string $s
|
||||
@@ -625,7 +638,9 @@ class NativeWikiPage {
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
static public function get_file_ext($arr) {
|
||||
|
||||
if($arr['mimetype'] === 'text/bbcode')
|
||||
return '.bb';
|
||||
elseif($arr['mimetype'] === 'text/markdown')
|
||||
|
||||
@@ -116,7 +116,7 @@ class Queue {
|
||||
dbesc(($arr['driver']) ? $arr['driver'] : 'zot6'),
|
||||
dbesc($arr['posturl']),
|
||||
intval(1),
|
||||
intval(($arr['priority']) ? $arr['priority'] : 0),
|
||||
intval(isset($arr['priority']) ? $arr['priority'] : 0),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
@@ -134,7 +134,7 @@ class Queue {
|
||||
$base = null;
|
||||
$h = parse_url($outq['outq_posturl']);
|
||||
if($h !== false)
|
||||
$base = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
|
||||
$base = $h['scheme'] . '://' . $h['host'] . (isset($h['port']) ? ':' . $h['port'] : '');
|
||||
|
||||
if(($base) && ($base !== z_root()) && ($immediate)) {
|
||||
$y = q("select site_update, site_dead from site where site_url = '%s' ",
|
||||
|
||||
@@ -43,7 +43,7 @@ class ThreadItem {
|
||||
$observer = \App::get_observer();
|
||||
|
||||
// Prepare the children
|
||||
if($data['children']) {
|
||||
if(isset($data['children'])) {
|
||||
foreach($data['children'] as $item) {
|
||||
|
||||
/*
|
||||
|
||||
@@ -101,11 +101,14 @@ class Admin extends \Zotlabs\Web\Controller {
|
||||
|
||||
// pending registrations
|
||||
|
||||
$pdg = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d ) > 0 ",
|
||||
intval(ACCOUNT_PENDING)
|
||||
// $pdg = q("SELECT account.*, register.reg_hash from account left join register on account_id = register.reg_uid // where (account_flags & %d ) > 0 ",
|
||||
// intval(ACCOUNT_PENDING)
|
||||
// );
|
||||
$pdg = q("SELECT COUNT(*) AS pdg FROM register WHERE reg_vital = 1 AND reg_expires > '%s' ",
|
||||
dbesc(date('Y-m-d H:i:s'))
|
||||
);
|
||||
|
||||
$pending = (($pdg) ? count($pdg) : 0);
|
||||
$pending = ($pdg ? $pdg[0]['pdg'] : 0);
|
||||
|
||||
// available channels, primary and clones
|
||||
$channels = array();
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Zotlabs\Module\Admin;
|
||||
|
||||
|
||||
class Accounts {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle POST actions on accounts admin page.
|
||||
*
|
||||
@@ -15,14 +15,105 @@ class Accounts {
|
||||
*
|
||||
*/
|
||||
|
||||
const MYP = 'ZAR'; // ZAR2x
|
||||
const VERSION = '2.0.0';
|
||||
|
||||
function post() {
|
||||
|
||||
$pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() );
|
||||
$users = ( x($_POST, 'user') ? $_POST['user'] : array() );
|
||||
$blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : array() );
|
||||
|
||||
|
||||
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts');
|
||||
|
||||
|
||||
$isajax = is_ajax();
|
||||
$rc = 0;
|
||||
|
||||
If (!is_site_admin()) {
|
||||
if ($isajax) {
|
||||
killme();
|
||||
exit;
|
||||
}
|
||||
goaway(z_root() . '/');
|
||||
}
|
||||
|
||||
if ($isajax) {
|
||||
//$debug = print_r($_SESSION[self::MYP],true);
|
||||
$zarop = (x($_POST['zardo']) && preg_match('/^[ad]{1,1}$/', $_POST['zardo']) )
|
||||
? $_POST['zardo'] : '';
|
||||
// zarat arrives with leading underscore _n
|
||||
$zarat = (x($_POST['zarat']) && preg_match('/^_{1,1}[0-9]{1,6}$/', $_POST['zarat']) )
|
||||
? substr($_POST['zarat'],1) : '';
|
||||
$zarse = (x($_POST['zarse']) && preg_match('/^[0-9a-f]{8,8}$/', $_POST['zarse']) )
|
||||
? hex2bin($_POST['zarse']) : '';
|
||||
|
||||
if ($zarop && $zarat >= 0 && $zarse && $zarse == $_SESSION[self::MYP]['h'][$zarat]) {
|
||||
|
||||
//
|
||||
if ($zarop == 'd') {
|
||||
$rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
|
||||
intval($_SESSION[self::MYP]['i'][$zarat]),
|
||||
dbesc($_SESSION[self::MYP]['h'][$zarat])
|
||||
);
|
||||
$rc = '×';
|
||||
}
|
||||
elseif ($zarop == 'a') {
|
||||
// approval, REGISTER_DENIED by user 0x0040, REGISTER_AGREED by user 0x0020 @Regate
|
||||
$rd = q("UPDATE register SET reg_flags = (reg_flags & ~ 16), "
|
||||
. " reg_vital = (CASE (reg_flags & ~ 48) WHEN 0 THEN 0 ELSE 1 END) "
|
||||
. " WHERE reg_vital = 1 AND reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
|
||||
intval($_SESSION[self::MYP]['i'][$zarat]),
|
||||
dbesc($_SESSION[self::MYP]['h'][$zarat])
|
||||
);
|
||||
$rc = 0;
|
||||
$rs = q("SELECT * from register WHERE reg_id = %d ",
|
||||
intval($_SESSION[self::MYP]['i'][$zarat])
|
||||
);
|
||||
if ($rs && ($rs[0]['reg_flags'] & ~ 48) == 0) {
|
||||
// create account
|
||||
$rc = 'ok'.$rs[0]['reg_id'];
|
||||
$ac = create_account_from_register($rs[0]);
|
||||
if ( $ac['success'] ) {
|
||||
$rc .= '✔';
|
||||
|
||||
$auto_create = get_config('system','auto_channel_create',1);
|
||||
|
||||
if($auto_create) {
|
||||
$reonar = json_decode($rs[0]['reg_stuff'], true);
|
||||
// prepare channel creation
|
||||
if($reonar['chan.name'])
|
||||
set_aconfig($ac['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']);
|
||||
|
||||
if($reonar['chan.did1'])
|
||||
set_aconfig($ac['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']);
|
||||
|
||||
$permissions_role = get_config('system','default_permissions_role');
|
||||
if($permissions_role)
|
||||
set_aconfig($ac['account']['account_id'], 'register', 'permissions_role', $permissions_role);
|
||||
|
||||
// create channel
|
||||
$new_channel = auto_channel_create($ac['account']['account_id']);
|
||||
|
||||
if($new_channel['success']) {
|
||||
$rc .= ' c,ok' . $new_channel['channel']['channel_id'] . '✔';
|
||||
}
|
||||
else {
|
||||
$rc .= ' c ×';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
$rc='oh ×';
|
||||
}
|
||||
}
|
||||
echo json_encode(array('re' => $zarop, 'at' => '_' . $zarat, 'rc' => $rc));
|
||||
}
|
||||
killme();
|
||||
exit;
|
||||
}
|
||||
|
||||
// change to switch structure?
|
||||
// account block/unblock button was submitted
|
||||
if (x($_POST, 'page_accounts_block')) {
|
||||
@@ -55,7 +146,7 @@ class Accounts {
|
||||
account_deny($hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
goaway(z_root() . '/admin/accounts' );
|
||||
}
|
||||
|
||||
@@ -75,19 +166,21 @@ class Accounts {
|
||||
$account = q("SELECT * FROM account WHERE account_id = %d",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
|
||||
if (! $account) {
|
||||
notice( t('Account not found') . EOL);
|
||||
goaway(z_root() . '/admin/accounts' );
|
||||
}
|
||||
|
||||
|
||||
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts', 't');
|
||||
|
||||
|
||||
$debug = '';
|
||||
|
||||
switch (argv(2)){
|
||||
case 'delete':
|
||||
// delete user
|
||||
account_remove($uid,true,false);
|
||||
|
||||
|
||||
notice( sprintf(t("Account '%s' deleted"), $account[0]['account_email']) . EOL);
|
||||
break;
|
||||
case 'block':
|
||||
@@ -95,7 +188,7 @@ class Accounts {
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
|
||||
notice( sprintf( t("Account '%s' blocked") , $account[0]['account_email']) . EOL);
|
||||
break;
|
||||
case 'unblock':
|
||||
@@ -103,27 +196,74 @@ class Accounts {
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
|
||||
notice( sprintf( t("Account '%s' unblocked"), $account[0]['account_email']) . EOL);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
goaway(z_root() . '/admin/accounts' );
|
||||
}
|
||||
|
||||
/* get pending */
|
||||
$pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d )>0 ",
|
||||
intval(ACCOUNT_PENDING)
|
||||
);
|
||||
|
||||
|
||||
$tao = 'tao.zar.zarax = ' . "'" . '<img src="' . z_root() . '/images/zapax16.gif">' . "';\n";
|
||||
|
||||
|
||||
// by default we will only return verified results. if reg_all is set we will return everything''
|
||||
$get_all = isset($_REQUEST['get_all']);
|
||||
$pending = get_pending_accounts($get_all);
|
||||
|
||||
unset($_SESSION[self::MYP]);
|
||||
|
||||
if ($pending) {
|
||||
// collect and group all ip
|
||||
$atips = dbq("SELECT reg_atip AS atip, COUNT(reg_atip) AS atips FROM register
|
||||
WHERE reg_vital = 1 GROUP BY reg_atip"
|
||||
);
|
||||
|
||||
(($atips) ? $atipn = array_column($atips, 'atips', 'atip') : $atipn = ['' => 0]);
|
||||
|
||||
$tao .= 'tao.zar.zarar = {';
|
||||
foreach ($pending as $n => $v) {
|
||||
|
||||
$stuff = json_decode($v['reg_stuff'], true);
|
||||
|
||||
if(isset($stuff['msg'])) {
|
||||
$pending[$n]['msg'] = $stuff['msg'];
|
||||
}
|
||||
|
||||
if (array_key_exists($v['reg_atip'], $atipn)) {
|
||||
$pending[$n]['reg_atip'] = $v['reg_atip'];
|
||||
$pending[$n]['reg_atip_n'] = $atipn[$v['reg_atip']];
|
||||
}
|
||||
|
||||
$pending[$n]['status'] = '';
|
||||
if($pending[$n]['reg_flags'] & ACCOUNT_UNVERIFIED > 0)
|
||||
$pending[$n]['status'] = [t('Unverified'), 'bg-warning'];
|
||||
|
||||
if($pending[$n]['status'] && $pending[$n]['reg_expires'] < datetime_convert())
|
||||
$pending[$n]['status'] = [t('Expired'), 'bg-danger text-white'];
|
||||
|
||||
// timezone adjust date_time for display
|
||||
$pending[$n]['reg_created'] = datetime_convert('UTC', date_default_timezone_get(), $pending[$n]['reg_created']);
|
||||
$pending[$n]['reg_startup'] = datetime_convert('UTC', date_default_timezone_get(), $pending[$n]['reg_startup']);
|
||||
$pending[$n]['reg_expires'] = datetime_convert('UTC', date_default_timezone_get(), $pending[$n]['reg_expires']);
|
||||
|
||||
// better secure
|
||||
$tao .= $n . ": '" . substr(bin2hex($v['reg_hash']),0,8) . "',";
|
||||
$_SESSION[self::MYP]['h'][] = substr($v['reg_hash'],0,4);
|
||||
$_SESSION[self::MYP]['i'][] = $v['reg_id'];
|
||||
}
|
||||
$tao = rtrim($tao,',') . '};' . "\n";
|
||||
}
|
||||
// <- hilmar]
|
||||
|
||||
/* get accounts */
|
||||
|
||||
|
||||
$total = q("SELECT count(*) as total FROM account");
|
||||
if (count($total)) {
|
||||
\App::set_pager_total($total[0]['total']);
|
||||
\App::set_pager_itemspage(100);
|
||||
}
|
||||
|
||||
|
||||
$serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : '');
|
||||
|
||||
$key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'account_id');
|
||||
@@ -134,8 +274,8 @@ class Accounts {
|
||||
$base = z_root() . '/admin/accounts?f=';
|
||||
$odir = (($dir === 'asc') ? '0' : '1');
|
||||
|
||||
$users = q("SELECT account_id , account_email, account_lastlog, account_created, account_expires, account_service_class, ( account_flags & %d ) > 0 as blocked,
|
||||
(SELECT %s FROM channel as ch WHERE ch.channel_account_id = ac.account_id and ch.channel_removed = 0 ) as channels FROM account as ac
|
||||
$users = q("SELECT account_id , account_email, account_lastlog, account_created, account_expires, account_service_class, ( account_flags & %d ) > 0 as blocked,
|
||||
(SELECT %s FROM channel as ch WHERE ch.channel_account_id = ac.account_id and ch.channel_removed = 0 ) as channels FROM account as ac
|
||||
where true $serviceclass and account_flags != %d order by $key $dir limit %d offset %d ",
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
db_concat('ch.channel_address', ' '),
|
||||
@@ -143,15 +283,15 @@ class Accounts {
|
||||
intval(\App::$pager['itemspage']),
|
||||
intval(\App::$pager['start'])
|
||||
);
|
||||
|
||||
|
||||
// function _setup_users($e){
|
||||
// $accounts = Array(
|
||||
// t('Normal Account'),
|
||||
// t('Normal Account'),
|
||||
// t('Soapbox Account'),
|
||||
// t('Community/Celebrity Account'),
|
||||
// t('Automatic Friend Account')
|
||||
// );
|
||||
|
||||
|
||||
// $e['page_flags'] = $accounts[$e['page-flags']];
|
||||
// $e['register_date'] = relative_date($e['register_date']);
|
||||
// $e['login_date'] = relative_date($e['login_date']);
|
||||
@@ -159,49 +299,57 @@ class Accounts {
|
||||
// return $e;
|
||||
// }
|
||||
// $users = array_map("_setup_users", $users);
|
||||
|
||||
|
||||
$t = get_markup_template('admin_accounts.tpl');
|
||||
$o = replace_macros($t, array(
|
||||
// strings //
|
||||
'$debug' => $debug,
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Accounts'),
|
||||
'$submit' => t('Submit'),
|
||||
'$select_all' => t('select all'),
|
||||
'$h_pending' => t('Registrations waiting for confirm'),
|
||||
'$th_pending' => array( t('Request date'), t('Email') ),
|
||||
'$no_pending' => t('No registrations.'),
|
||||
'$get_all' => (($get_all) ? t('Show verified registrations') : t('Show all registrations')),
|
||||
'$get_all_link' => (($get_all) ? z_root() .'/admin/accounts' : z_root() .'/admin/accounts?get_all'),
|
||||
'$sel_tall' => t('Select toggle'),
|
||||
'$sel_deny' => t('Deny selected'),
|
||||
'$sel_aprv' => t('Approve selected'),
|
||||
'$h_pending' => (($get_all) ? t('All registrations') : t('Verified registrations waiting for approval')),
|
||||
'$th_pending' => array(t('Request date'), 'dId2', t('Email'), 'IP', t('Requests')),
|
||||
'$no_pending' => (($get_all) ? t('No registrations available') : t('No verified registrations available')),
|
||||
'$approve' => t('Approve'),
|
||||
'$deny' => t('Deny'),
|
||||
'$delete' => t('Delete'),
|
||||
'$block' => t('Block'),
|
||||
'$unblock' => t('Unblock'),
|
||||
'$verified' => t('Verified'),
|
||||
'$not_verified' => t('Not yet verified'),
|
||||
'$odir' => $odir,
|
||||
'$base' => $base,
|
||||
'$h_users' => t('Accounts'),
|
||||
'$th_users' => array(
|
||||
'$th_users' => array(
|
||||
[ t('ID'), 'account_id' ],
|
||||
[ t('Email'), 'account_email' ],
|
||||
[ t('All Channels'), 'channels' ],
|
||||
[ t('All channels'), 'channels' ],
|
||||
[ t('Register date'), 'account_created' ],
|
||||
[ t('Last login'), 'account_lastlog' ],
|
||||
[ t('Expires'), 'account_expires' ],
|
||||
[ t('Service Class'), 'account_service_class'] ),
|
||||
|
||||
'$confirm_delete_multi' => t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
'$confirm_delete' => t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
|
||||
[ t('Service class'), 'account_service_class'] ),
|
||||
|
||||
'$confirm_delete_multi' => p2j(t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?')),
|
||||
'$confirm_delete' => p2j(t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?')),
|
||||
|
||||
'$form_security_token' => get_form_security_token("admin_accounts"),
|
||||
|
||||
|
||||
// values //
|
||||
'$baseurl' => z_root(),
|
||||
|
||||
'$pending' => $pending,
|
||||
'$users' => $users,
|
||||
'$baseurl' => z_root(),
|
||||
'$tao' => $tao,
|
||||
'$pending' => $pending,
|
||||
'$users' => $users,
|
||||
'$msg' => t('Message')
|
||||
));
|
||||
$o .= paginate($a);
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -173,4 +173,4 @@ class Channels {
|
||||
return $o;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,25 @@ namespace Zotlabs\Module\Admin;
|
||||
|
||||
class Site {
|
||||
|
||||
|
||||
/**
|
||||
* @brief POST handler for Admin Site Page.
|
||||
*
|
||||
*/
|
||||
function post(){
|
||||
// [hilmar->
|
||||
$this->isajax = is_ajax();
|
||||
$this->eol = $this->isajax ? "\n" : EOL;
|
||||
// ]
|
||||
if (!x($_POST, 'page_site')) {
|
||||
return;
|
||||
// [
|
||||
if (!$this->isajax)
|
||||
// ]
|
||||
return;
|
||||
}
|
||||
// [
|
||||
$this->msgbg = '';
|
||||
// <-hilmar]
|
||||
|
||||
check_form_security_token_redirectOnErr('/admin/site', 'admin_site');
|
||||
|
||||
@@ -24,14 +35,17 @@ class Site {
|
||||
$siteinfo = ((x($_POST,'siteinfo')) ? trim($_POST['siteinfo']) : '');
|
||||
$language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : '');
|
||||
$theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : '');
|
||||
// $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : '');
|
||||
// $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : '');
|
||||
// $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : '');
|
||||
// $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : '');
|
||||
$maximagesize = ((x($_POST,'maximagesize')) ? intval(trim($_POST['maximagesize'])) : 0);
|
||||
|
||||
$register_policy = ((x($_POST,'register_policy')) ? intval(trim($_POST['register_policy'])) : 0);
|
||||
$register_wo_email = ((x($_POST,'register_wo_email')) ? intval(trim($_POST['register_wo_email'])) : 0);
|
||||
$minimum_age = ((x($_POST,'minimum_age')) ? intval(trim($_POST['minimum_age'])) : 13);
|
||||
$access_policy = ((x($_POST,'access_policy')) ? intval(trim($_POST['access_policy'])) : 0);
|
||||
$invite_only = ((x($_POST,'invite_only')) ? True : False);
|
||||
$reg_autochannel = ((x($_POST,'auto_channel_create')) ? True : False);
|
||||
$invitation_only = ((x($_POST,'invitation_only')) ? True : False);
|
||||
$invitation_also = ((x($_POST,'invitation_also')) ? True : False);
|
||||
$abandon_days = ((x($_POST,'abandon_days')) ? intval(trim($_POST['abandon_days'])) : 0);
|
||||
|
||||
$register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : '');
|
||||
@@ -75,6 +89,16 @@ class Site {
|
||||
$maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
|
||||
$feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
|
||||
$verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
|
||||
$register_perday = ((x($_POST,'register_perday')) ? intval(trim($_POST['register_perday'])) : 50);
|
||||
$register_sameip = ((x($_POST,'register_sameip')) ? intval(trim($_POST['register_sameip'])) : 3);
|
||||
|
||||
$regdelayn = ((x($_POST,'zardelayn')) ? intval(trim($_POST['zardelayn'])) : 0);
|
||||
$regdelayu = ((x($_POST,'zardelay')) ? notags(trim($_POST['zardelay'])) : '');
|
||||
$reg_delay = (preg_match('/^[a-z]{1,1}$/', $regdelayu) ? $regdelayn . $regdelayu : '');
|
||||
$regexpiren = ((x($_POST,'zarexpiren')) ? intval(trim($_POST['zarexpiren'])) : 0);
|
||||
$regexpireu = ((x($_POST,'zarexpire')) ? notags(trim($_POST['zarexpire'])) : '');
|
||||
$reg_expire = (preg_match('/^[a-z]{1,1}$/', $regexpireu) ? $regexpiren . $regexpireu : '');
|
||||
|
||||
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
|
||||
$force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000);
|
||||
$pub_incl = escape_tags(trim($_POST['pub_incl']));
|
||||
@@ -82,6 +106,35 @@ class Site {
|
||||
|
||||
$permissions_role = escape_tags(trim($_POST['permissions_role']));
|
||||
|
||||
// [hilmar->
|
||||
$this->register_duty = ((x($_POST,'register_duty')) ? notags(trim($_POST['register_duty'])) : '');
|
||||
if (! preg_match('/^[0-9 .,:\-]{0,191}$/', $this->register_duty)) {
|
||||
$this->msgbg .= 'ZAR0131E,' . t('Invalid input') . $this->eol;
|
||||
$this->error++;
|
||||
} else {
|
||||
|
||||
$this->duty();
|
||||
|
||||
if ($this->isajax) {
|
||||
echo json_encode(array('msgbg' => $this->msgbg, 'me' => 'zar'));
|
||||
// that mission is complete
|
||||
killme();
|
||||
exit;
|
||||
|
||||
} else {
|
||||
|
||||
//logger( print_r( $this->msgbg, true) );
|
||||
//logger( print_r( $this->joo, true) );
|
||||
if ($this->error === 0) {
|
||||
set_config('system', 'register_duty', $this->register_duty);
|
||||
set_config('system', 'register_duty_jso', $this->joo);
|
||||
} else {
|
||||
notice('ZAR0130E,'.t('Errors') . ': ' . $this->error) . EOL . $this->msgfg;
|
||||
}
|
||||
}
|
||||
}
|
||||
// <-hilmar]
|
||||
|
||||
set_config('system', 'feed_contacts', $feed_contacts);
|
||||
set_config('system', 'delivery_interval', $delivery_interval);
|
||||
set_config('system', 'delivery_batch_count', $delivery_batch_count);
|
||||
@@ -96,6 +149,10 @@ class Site {
|
||||
set_config('system', 'login_on_homepage', $login_on_homepage);
|
||||
set_config('system', 'enable_context_help', $enable_context_help);
|
||||
set_config('system', 'verify_email', $verify_email);
|
||||
set_config('system', 'max_daily_registrations', $register_perday);
|
||||
set_config('system', 'register_sameip', $register_sameip);
|
||||
set_config('system', 'register_delay', $reg_delay);
|
||||
set_config('system', 'register_expire', $reg_expire);
|
||||
set_config('system', 'default_expire_days', $default_expire_days);
|
||||
set_config('system', 'active_expire_days', $active_expire_days);
|
||||
set_config('system', 'reply_address', $reply_address);
|
||||
@@ -126,17 +183,20 @@ class Site {
|
||||
set_config('system','siteinfo',$siteinfo);
|
||||
set_config('system', 'language', $language);
|
||||
set_config('system', 'theme', $theme);
|
||||
// if ( $theme_mobile === '---' ) {
|
||||
// del_config('system', 'mobile_theme');
|
||||
// } else {
|
||||
// set_config('system', 'mobile_theme', $theme_mobile);
|
||||
// }
|
||||
// set_config('system','site_channel', $site_channel);
|
||||
// if ( $theme_mobile === '---' ) {
|
||||
// del_config('system', 'mobile_theme');
|
||||
// } else {
|
||||
// set_config('system', 'mobile_theme', $theme_mobile);
|
||||
// }
|
||||
// set_config('system','site_channel', $site_channel);
|
||||
set_config('system','maximagesize', $maximagesize);
|
||||
|
||||
set_config('system','register_policy', $register_policy);
|
||||
set_config('system','register_wo_email', $register_wo_email);
|
||||
set_config('system','minimum_age', $minimum_age);
|
||||
set_config('system','invitation_only', $invite_only);
|
||||
set_config('system','auto_channel_create', $reg_autochannel);
|
||||
set_config('system', 'invitation_only', $invitation_only);
|
||||
set_config('system', 'invitation_also', $invitation_also);
|
||||
set_config('system','access_policy', $access_policy);
|
||||
set_config('system','account_abandon_days', $abandon_days);
|
||||
set_config('system','register_text', $register_text);
|
||||
@@ -260,6 +320,8 @@ class Site {
|
||||
REGISTER_APPROVE => t("Yes - with approval"),
|
||||
REGISTER_OPEN => t("Yes")
|
||||
);
|
||||
$this->register_duty = get_config('system', 'register_duty', '-:-');
|
||||
$register_perday = get_config('system','max_daily_registrations', 50);
|
||||
|
||||
/* Acess policy */
|
||||
$access_choices = Array(
|
||||
@@ -286,9 +348,66 @@ class Site {
|
||||
$homelogin = get_config('system','login_on_homepage');
|
||||
$enable_context_help = get_config('system','enable_context_help');
|
||||
|
||||
// for reuse reg_delay and reg_expire
|
||||
$reg_rabots = array(
|
||||
'i' => t('Minute(s)'),
|
||||
'h' => t('Hour(s)') ,
|
||||
'd' => t('Day(s)') ,
|
||||
'w' => t('Week(s)') ,
|
||||
'm' => t('Month(s)') ,
|
||||
'y' => t('Year(s)')
|
||||
);
|
||||
$regdelay_n = $regdelay_u = false;
|
||||
$regdelay = get_config('system','register_delay');
|
||||
if ($regdelay)
|
||||
list($regdelay_n, $regdelay_u) = array(substr($regdelay,0,-1),substr($regdelay,-1));
|
||||
$reg_delay = replace_macros(get_markup_template('field_duration.qmc.tpl'),
|
||||
array(
|
||||
'label' => t('Register verification delay'),
|
||||
'qmc' => 'zar',
|
||||
'qmcid' => '',
|
||||
'help' => t('Time to wait before a registration can be verified'),
|
||||
'field' => array(
|
||||
'name' => 'delay',
|
||||
'title' => t('duration up from now'),
|
||||
'value' => ($regdelay_n === false ? 0 : $regdelay_n),
|
||||
'min' => '0',
|
||||
'max' => '99',
|
||||
'size' => '2',
|
||||
'default' => ($regdelay_u === false ? 'i' : $regdelay_u)
|
||||
),
|
||||
'rabot' => $reg_rabots
|
||||
)
|
||||
);
|
||||
$regexpire_n = $regexpire_u = false;
|
||||
$regexpire = get_config('system','register_expire');
|
||||
if ($regexpire)
|
||||
list($regexpire_n, $regexpire_u) = array(substr($regexpire,0,-1),substr($regexpire,-1));
|
||||
$reg_expire = replace_macros(get_markup_template('field_duration.qmc.tpl'),
|
||||
array(
|
||||
'label' => t('Register verification expiration time'),
|
||||
'qmc' => 'zar',
|
||||
'qmcid' => '',
|
||||
'help' => t('Time before an unverified registration will expire'),
|
||||
'field' => array(
|
||||
'name' => 'expire',
|
||||
'title' => t('duration up from now'),
|
||||
'value' => ($regexpire_n === false ? 3 : $regexpire_n),
|
||||
'min' => '0',
|
||||
'max' => '99',
|
||||
'size' => '2',
|
||||
'default' => ($regexpire_u === false ? 'd' : $regexpire_u)
|
||||
),
|
||||
'rabot' => $reg_rabots
|
||||
)
|
||||
);
|
||||
|
||||
$tao = '';
|
||||
$t = get_markup_template("admin_site.tpl");
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
// interfacing js vars
|
||||
'$tao' => $tao,
|
||||
'$page' => t('Site'),
|
||||
'$submit' => t('Submit'),
|
||||
'$registration' => t('Registration'),
|
||||
@@ -305,21 +424,87 @@ class Site {
|
||||
'$siteinfo' => array('siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode can be used here")),
|
||||
'$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
|
||||
'$theme' => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices),
|
||||
// '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile),
|
||||
// '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")),
|
||||
// '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile),
|
||||
// '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")),
|
||||
'$feed_contacts' => array('feed_contacts', t('Allow Feeds as Connections'),get_config('system','feed_contacts'),t('(Heavy system resource usage)')),
|
||||
'$maximagesize' => array('maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.")),
|
||||
'$register_policy' => array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices),
|
||||
'$invite_only' => array('invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. Above register policy must be set to Yes.")),
|
||||
'$minimum_age' => array('minimum_age', t("Minimum age"), (x(get_config('system','minimum_age'))?get_config('system','minimum_age'):13), t("Minimum age (in years) for who may register on this site.")),
|
||||
'$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), t("This is displayed on the public server site list."), $access_choices),
|
||||
'$register_text' => array('register_text', t("Register text"), htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")),
|
||||
|
||||
// Register
|
||||
// [hilmar->
|
||||
'$register_text' => [
|
||||
'register_text',
|
||||
t("Register text"),
|
||||
htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'),
|
||||
t("This text will be displayed prominently at the registration page")
|
||||
],
|
||||
'$register_policy' => [
|
||||
'register_policy',
|
||||
t("Does this site allow new member registration?"),
|
||||
get_config('system','register_policy'),
|
||||
"",
|
||||
$register_choices,
|
||||
],
|
||||
'$register_duty' => [
|
||||
'register_duty',
|
||||
t('Configure the registration open days/hours'),
|
||||
get_config('system', 'register_duty', '-:-'),
|
||||
t('Empty or \'-:-\' value will keep registration open 24/7 (default)') . EOL .
|
||||
t('Weekdays and hours must be separated by colon \':\', From-To ranges with a dash `-` example: 1:800-1200') . EOL .
|
||||
t('Weekday:Hour pairs must be separated by space \' \' example: 1:900-1700 2:900-1700') . EOL .
|
||||
t('From-To ranges must be separated by comma \',\' example: 1:800-1200,1300-1700 or 1-2,4-5:900-1700') . EOL .
|
||||
t('Advanced examples:') . ' 1-5:0900-1200,1300-1700 6:900-1230 ' . t('or') . ' 1-2,4-5:800-1800<br>' . EOL .
|
||||
'<a id="zar083a" class="btn btn-sm btn-outline-secondary zuia">' . t('Check your configuration') . '</a>'. EOL
|
||||
],
|
||||
'$register_perday' => [
|
||||
'register_perday',
|
||||
t('Max account registrations per day'),
|
||||
get_config('system', 'max_daily_registrations', 50),
|
||||
t('Unlimited if zero or no value - default 50')
|
||||
],
|
||||
'$register_sameip' => [
|
||||
'register_sameip',
|
||||
t('Max account registrations from same IP'),
|
||||
get_config('system', 'register_sameip', 3),
|
||||
t('Unlimited if zero or no value - default 3')
|
||||
],
|
||||
'$reg_delay' => $reg_delay,
|
||||
'$reg_expire' => $reg_expire,
|
||||
'$reg_autochannel' => [
|
||||
'auto_channel_create',
|
||||
t("Auto channel create"),
|
||||
get_config('system','auto_channel_create', 1),
|
||||
t("If disabled the channel will be created in a separate step during the registration process")
|
||||
],
|
||||
'$invitation_only' => [
|
||||
'invitation_only',
|
||||
t("Require invite code"),
|
||||
$invitation_only
|
||||
],
|
||||
'$invitation_also' => [
|
||||
'invitation_also',
|
||||
t("Allow invite code"),
|
||||
$invitation_also
|
||||
],
|
||||
'$verify_email' => [
|
||||
'verify_email',
|
||||
t("Require email address"),
|
||||
get_config('system','verify_email'),
|
||||
t("The provided email address will be verified (recommended)")
|
||||
],
|
||||
'$abandon_days' => [
|
||||
'abandon_days',
|
||||
t('Abandon account after x days'),
|
||||
get_config('system','account_abandon_days'),
|
||||
t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')
|
||||
],
|
||||
// <-hilmar]
|
||||
|
||||
'$role' => $role,
|
||||
'$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'pubstream' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")),
|
||||
'$mirror_frontpage' => array('mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting')),
|
||||
'$abandon_days' => array('abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')),
|
||||
'$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")),
|
||||
'$verify_email' => array('verify_email', t("Verify Email Addresses"), get_config('system','verify_email'), t("Check to verify email addresses used in account registration (recommended).")),
|
||||
'$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")),
|
||||
'$disable_discover_tab' => array('disable_discover_tab', t('Import Public Streams'), $discover_tab, t('Import and allow access to public content pulled from other sites. Warning: this content is unmoderated.')),
|
||||
'$site_firehose' => array('site_firehose', t('Site only Public Streams'), get_config('system','site_firehose'), t('Allow access to public content originating only from this site if Imported Public Streams are disabled.')),
|
||||
@@ -350,15 +535,184 @@ class Site {
|
||||
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
|
||||
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
|
||||
'$active_expire_days' => array('active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), ''),
|
||||
|
||||
'$sellpage' => array('site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root())),
|
||||
'$first_page' => array('first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles')),
|
||||
|
||||
'$location' => array('site_location', t('Optional: site location'), get_config('system','site_location',''), t('Region or country')),
|
||||
|
||||
|
||||
'$form_security_token' => get_form_security_token("admin_site"),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Admin page site common post submit and ajax interaction
|
||||
* @author hilmar runge
|
||||
* @since 2020-02-04
|
||||
* Configure register office duty weekdays and hours
|
||||
* Syntax: weekdays:hours [weekdays:hours]
|
||||
* [.d[,d-d.]]]:hhmm-hhmm[,hhmm-hhmm...]
|
||||
* ranges are between blanks, days are 1-7, where 1 = Monday
|
||||
* hours are [h]hmm 3-4digit 24 clock values
|
||||
* ie 0900-1200,1300-1800 for hours
|
||||
* ie 1-2,4,5 for weekdays
|
||||
* ie 1-2:900-1800 monday and tuesday open from 9 to 18h
|
||||
*
|
||||
* @var $register_duty is the input field from the admin -> site page
|
||||
* @return the results are in the class vars $error, $msgbg and $jsoo
|
||||
* $jsoo is
|
||||
*/
|
||||
|
||||
// 3-4 digit 24h clock regex
|
||||
const regxTime34 = '/^(?:2[0-3]|[01][0-9]|[0-9])[0-5][0-9]$/';
|
||||
var $wdconst = array('','mo','tu','we','th','fr','sa','so');
|
||||
|
||||
// in
|
||||
var $register_duty;
|
||||
// intermediate
|
||||
var $isajax;
|
||||
// return
|
||||
var $jsoo;
|
||||
var $msgbg;
|
||||
var $error = 0;
|
||||
var $msgfg = '';
|
||||
|
||||
private function duty() {
|
||||
|
||||
$aro=array_fill(1, 7, 0);
|
||||
|
||||
if ($this->isajax) {
|
||||
$op = (preg_match('/[a-z]{2,4}/', $_REQUEST['zarop'])) ? $_REQUEST['zarop'] : '';
|
||||
if ($op == 'zar083') {
|
||||
$this->msgbg = 'Testmode:' . $this->eol . $this->msgbg;
|
||||
} else {
|
||||
killme();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$ranges = preg_split('/\s+/', $this->register_duty);
|
||||
$this->msgbg .= '..ranges: ' . print_r(count($ranges),true) . $this->eol;
|
||||
|
||||
foreach ($ranges as $rn => $range) {
|
||||
list($ws,$hs,) = explode(':', $range);
|
||||
|
||||
$ws ? $arw = explode( ',', $ws) : $arw=array();
|
||||
$this->msgbg .= ($rn+1).'.weekday ranges: ' . count($arw) . $this->eol;
|
||||
// $this->msgbg .= print_r($arw,true);
|
||||
$hs ? $arh = explode( ',', $hs) : $arh=array();
|
||||
$this->msgbg .= ($rn+1).'.hour ranges: ' . count($arh) . $this->eol;
|
||||
|
||||
$this->msgbg .= ($rn+1).'.wdays: ' . ( $ws ? print_r($ws,true) : 'none') . ' : '
|
||||
. ' hours: ' . print_r($hs,true) . $this->eol;
|
||||
|
||||
// several hs may belog to one wd
|
||||
// aro[0] is tmp store
|
||||
foreach ($arh as $hs) {
|
||||
list($ho,$hc,) = explode( '-', $hs );
|
||||
|
||||
// no value forces open very early, and be sure having valid hhmm values
|
||||
!$ho ? $ho = "0000" : '';
|
||||
!$hc ? $hc = "0000" : ''; // pseudo
|
||||
if (preg_match(self::regxTime34, $ho)
|
||||
&& preg_match(self::regxTime34, $hc)) {
|
||||
|
||||
// fix pseudo, allow no reverse range
|
||||
$hc == "0000" || $ho > $hc ? $hc = "2400" : '';
|
||||
|
||||
$aro[0][$ho] = 0;
|
||||
$aro[0][$hc] = 1;
|
||||
|
||||
$this->msgbg .= ($ho ? ' .open:' . $ho : '') . ($hc ? ' close:' . $hc : '') .$this->eol;
|
||||
} else {
|
||||
$this->msgbg .= ' .' . t('Invalid 24h time value (hhmm/hmm)') . $this->eol;
|
||||
$this->msgfg .= ' .ZAR0132E,' . t('Invalid 24h time value (hhmm/hmm)') . $this->eol;
|
||||
$this->error++;
|
||||
}
|
||||
}
|
||||
|
||||
// the weekday(s) values or ranges
|
||||
foreach ($arw as $ds) {
|
||||
$wd=explode('-', $ds);
|
||||
array_key_exists("1", $wd) && $wd[1]=="" ? $wd[1] = "7" : ''; // a case 3-
|
||||
array_key_exists("1", $wd) && $wd[0]=="" ? $wd[0] = "1" : ''; // a case -3
|
||||
!array_key_exists("1", $wd) ? $wd[1] = $wd[0] : ''; // a case 3
|
||||
if ($wd[0] > $wd[1]) continue; // reverse order will be ignored // a case 5-3
|
||||
if (preg_match('/^[1-7]{1}$/', $wd[0])) {
|
||||
if (preg_match('/^[1-7]{1}$/', $wd[1])) {
|
||||
// $this->msgbg .= print_r($wd,true);
|
||||
for ($i=$wd[0]; $i<=$wd[1]; $i++) {
|
||||
// take the tmp store for the selected day(s)
|
||||
$aro[$i]=$aro[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//$this->msgbg .= 'aro0: ' . print_r($aro,true) . $this->eol; // 4devels
|
||||
// clear the tmp store
|
||||
$aro[0]=array();
|
||||
}
|
||||
// discart the tmp store
|
||||
unset($aro[0]);
|
||||
// not configured days close at the beginning 0000h
|
||||
for ($i=1;$i<=7;$i++) { is_array($aro[$i]) ? '' : $aro[$i] = array("0000" => 1); }
|
||||
// $this->msgbg .= 'aro: ' . print_r($aro,true) . $this->eol; // 4devels
|
||||
|
||||
if ($this->isajax) {
|
||||
// tell what we have
|
||||
// $this->msgbg .= 'aro0: ' . print_r($aro,true) . $this->eol; // 4devels
|
||||
$this->msgbg .= 'Duty time table:' . $this->eol;
|
||||
foreach ($aro as $dow => $hrs) {
|
||||
$this->msgbg .= ' ' . $this->wdconst[$dow] . ' ';
|
||||
// $this->msgbg .= '**' . print_r($hrs,true);
|
||||
foreach ($hrs as $h => $o) {
|
||||
$this->msgbg .= ((!$o) ? $h . ':open' : $h . ':close') . ', ';
|
||||
}
|
||||
$this->msgbg = rtrim($this->msgbg, ', ') . $this->eol;
|
||||
}
|
||||
|
||||
$this->msgbg .= 'Generating 6 random times to check duty hours: ' . $this->eol;
|
||||
// we only need some random dates from anyway in past or future
|
||||
// because only the weekday and the clock is to test
|
||||
for ($i=0; $i<6; $i++) {
|
||||
$adow = rand(1, 7); // 1 to 7 (days)
|
||||
$cdow = $this->wdconst[$adow];
|
||||
// below is the essential algo to verify a date (of format Hi) meets an open or closed condition
|
||||
$t = date('Hi', ( rand(time(), 60*60*24+time()) ) );
|
||||
$how='close';
|
||||
foreach ($aro[$adow] as $o => $v) {
|
||||
// $this->msgbg .= 'debug: ' . $o . ' gt ' . $t . ' / ' . $v . $this->eol; // 4devels
|
||||
if ($o > $t) {
|
||||
$how = ($v ? 'open' : 'close');
|
||||
break;
|
||||
}
|
||||
}
|
||||
// now we know
|
||||
$this->msgbg .= ' ' . $cdow . '.' . $t . '=' . $how . ', ';
|
||||
}
|
||||
$this->msgbg = rtrim($this->msgbg, ', ') . $this->eol;
|
||||
}
|
||||
|
||||
/*
|
||||
//$jov1 = array( 'view1' => $aro, 'view2' => '');
|
||||
$jov2=array();
|
||||
foreach ($aro as $d => $ts) {
|
||||
foreach ($ts as $t => $ft) {
|
||||
$jov2['view2'][$ft][] = $d.$t;
|
||||
//$ft=="1" && $t=="0000" ? $jov2['view2']["0"][] = $d."2400" : '';
|
||||
}
|
||||
}
|
||||
$this->msgbg .= print_r($jov2, true) . $this->eol; // 4devels
|
||||
*/
|
||||
|
||||
$this->joo = json_encode($aro);
|
||||
// $this->msgbg .= $this->joo . $this->eol; // 4devels
|
||||
// $this->msgbg .= print_r($aro, true) . $this->eol; // 4devels
|
||||
$okko = (json_decode($this->joo, true) ? true : false);
|
||||
if (!$okko) {
|
||||
$this->msgbg .= 'ZAR0139D,json 4 duty KO crash' . $this->eol;
|
||||
$this->msgfg .= 'ZAR0139D,json 4 duty KO crash' . $this->eol;
|
||||
$this->error++;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ class Bookmarks extends \Zotlabs\Web\Controller {
|
||||
|
||||
nav_set_selected('Bookmarks');
|
||||
|
||||
$item_id = intval($_REQUEST['item']);
|
||||
$burl = trim($_REQUEST['burl']);
|
||||
$item_id = (isset($_REQUEST['item']) ? $_REQUEST['item'] : false);
|
||||
$burl = (isset($_REQUEST['burl']) ? trim($_REQUEST['burl']) : '');
|
||||
|
||||
if(! $item_id)
|
||||
return;
|
||||
@@ -38,7 +38,7 @@ class Bookmarks extends \Zotlabs\Web\Controller {
|
||||
|
||||
$item = $i[0];
|
||||
|
||||
$terms = get_terms_oftype($item['term'],TERM_BOOKMARK);
|
||||
$terms = (x($item, 'term') ? get_terms_oftype($item['term'],TERM_BOOKMARK) : false);
|
||||
|
||||
if($terms) {
|
||||
require_once('include/bookmarks.php');
|
||||
|
||||
@@ -19,45 +19,45 @@ class Cal extends Controller {
|
||||
if(observer_prohibited()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(argc() > 1) {
|
||||
$nick = argv(1);
|
||||
|
||||
|
||||
profile_load($nick);
|
||||
|
||||
|
||||
$channelx = channelx_by_nick($nick);
|
||||
|
||||
|
||||
if(! $channelx) {
|
||||
notice( t('Channel not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
App::$data['channel'] = $channelx;
|
||||
|
||||
|
||||
$observer = App::get_observer();
|
||||
App::$data['observer'] = $observer;
|
||||
|
||||
|
||||
head_set_icon(App::$data['channel']['xchan_photo_s']);
|
||||
|
||||
|
||||
App::$page['htmlhead'] .= "<script> var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
if(observer_prohibited()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$channel = App::$data['channel'];
|
||||
|
||||
// since we don't currently have an event permission - use the stream permission
|
||||
|
||||
|
||||
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) {
|
||||
notice( t('Permissions denied.') . EOL);
|
||||
return;
|
||||
@@ -76,10 +76,10 @@ class Cal extends Controller {
|
||||
|
||||
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts') || App::$profile['hide_friends'])
|
||||
$sql_extra .= " and etype != 'birthday' ";
|
||||
|
||||
|
||||
$first_day = feature_enabled($channel['channel_id'], 'cal_first_day');
|
||||
$first_day = (($first_day) ? $first_day : 0);
|
||||
|
||||
|
||||
$start = '';
|
||||
$finish = '';
|
||||
|
||||
@@ -87,7 +87,7 @@ class Cal extends Controller {
|
||||
if (x($_GET,'start')) $start = $_GET['start'];
|
||||
if (x($_GET,'end')) $finish = $_GET['end'];
|
||||
}
|
||||
|
||||
|
||||
$start = datetime_convert('UTC','UTC',$start);
|
||||
$finish = datetime_convert('UTC','UTC',$finish);
|
||||
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
|
||||
@@ -107,10 +107,10 @@ class Cal extends Controller {
|
||||
// Noting this for now - it will need to be fixed here and in Friendica.
|
||||
// Ultimately the finish date shouldn't be involved in the query.
|
||||
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
|
||||
from event left join item on event.event_hash = item.resource_id
|
||||
where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid
|
||||
AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )
|
||||
OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' ))
|
||||
from event left join item on event.event_hash = item.resource_id
|
||||
where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid
|
||||
AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )
|
||||
OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' ))
|
||||
$sql_extra",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($start),
|
||||
@@ -119,7 +119,7 @@ class Cal extends Controller {
|
||||
dbesc($adjust_finish)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r,true);
|
||||
@@ -127,20 +127,16 @@ class Cal extends Controller {
|
||||
}
|
||||
|
||||
$events = [];
|
||||
|
||||
|
||||
if($r) {
|
||||
|
||||
foreach($r as $rr) {
|
||||
|
||||
$tz = get_iconfig($rr, 'event', 'timezone');
|
||||
if(! $tz)
|
||||
$tz = 'UTC';
|
||||
|
||||
$start = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c'));
|
||||
$start = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c'));
|
||||
if ($rr['nofinish']){
|
||||
$end = null;
|
||||
} else {
|
||||
$end = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c'));
|
||||
$end = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c'));
|
||||
}
|
||||
|
||||
$html = '';
|
||||
@@ -149,6 +145,10 @@ class Cal extends Controller {
|
||||
$html = format_event_html($rr);
|
||||
}
|
||||
|
||||
$tz = get_iconfig($rr, 'event', 'timezone');
|
||||
if(! $tz)
|
||||
$tz = 'UTC';
|
||||
|
||||
$events[] = array(
|
||||
'calendar_id' => 'channel_calendar',
|
||||
'rw' => true,
|
||||
@@ -178,7 +178,7 @@ class Cal extends Controller {
|
||||
echo json_encode($events);
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
if (x($_GET,'id')) {
|
||||
$o = replace_macros(get_markup_template("cal_event.tpl"), [
|
||||
'$events' => $events
|
||||
@@ -210,7 +210,7 @@ class Cal extends Controller {
|
||||
]);
|
||||
|
||||
return $o;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ class Cdav extends Controller {
|
||||
$auth = new \Zotlabs\Storage\BasicAuth();
|
||||
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . 'CalDAV/CardDAV');
|
||||
|
||||
if (local_channel()) {
|
||||
if(local_channel()) {
|
||||
|
||||
logger('loggedin');
|
||||
|
||||
@@ -153,9 +153,9 @@ class Cdav extends Controller {
|
||||
$auth->observer = $channel['channel_hash'];
|
||||
|
||||
$principalUri = 'principals/' . $channel['channel_address'];
|
||||
if(!cdav_principal($principalUri)) {
|
||||
if(! cdav_principal($principalUri)) {
|
||||
$this->activate($pdo, $channel);
|
||||
if(!cdav_principal($principalUri)) {
|
||||
if(! cdav_principal($principalUri)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -168,21 +168,24 @@ class Cdav extends Controller {
|
||||
|
||||
if($httpmethod === 'PUT' || $httpmethod === 'DELETE') {
|
||||
|
||||
$channel = channelx_by_nick(argv(2));
|
||||
$principalUri = 'principals/' . $channel['channel_address'];
|
||||
$httpuri = $_SERVER['REQUEST_URI'];
|
||||
|
||||
logger("debug: method: " . $httpmethod, LOGGER_DEBUG);
|
||||
logger("debug: uri: " . $httpuri, LOGGER_DEBUG);
|
||||
|
||||
if(strpos($httpuri, 'cdav/addressbooks')) {
|
||||
if(strpos($httpuri, 'cdav/addressbooks') !== false) {
|
||||
$sync = 'addressbook';
|
||||
$cdavtable = 'addressbooks';
|
||||
}
|
||||
elseif(strpos($httpuri, 'cdav/calendars')) {
|
||||
elseif(strpos($httpuri, 'cdav/calendars') !== false) {
|
||||
$sync = 'calendar';
|
||||
$cdavtable = 'calendarinstances';
|
||||
}
|
||||
else
|
||||
else {
|
||||
$sync = false;
|
||||
}
|
||||
|
||||
if($sync) {
|
||||
|
||||
@@ -191,14 +194,13 @@ class Cdav extends Controller {
|
||||
|
||||
logger("debug: body: " . $httpbody, LOGGER_DEBUG);
|
||||
|
||||
if($x = get_cdav_id($principalUri, explode("/", $httpuri)[4], $cdavtable)) {
|
||||
if($x = get_cdav_id($principalUri, argv(3), $cdavtable)) {
|
||||
|
||||
$cdavdata = $this->get_cdav_data($x['id'], $cdavtable);
|
||||
|
||||
$etag = (isset($_SERVER['HTTP_IF_MATCH']) ? $_SERVER['HTTP_IF_MATCH'] : false);
|
||||
|
||||
// delete
|
||||
if($httpmethod === 'DELETE' && $cdavdata['etag'] == $etag)
|
||||
if($httpmethod === 'DELETE' && $cdavdata['etag'] == $etag) {
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'delete_card',
|
||||
@@ -206,18 +208,18 @@ class Cdav extends Controller {
|
||||
'carduri' => $uri
|
||||
]
|
||||
]);
|
||||
}
|
||||
else {
|
||||
if($etag) {
|
||||
if($etag && $cdavdata['etag'] !== $etag) {
|
||||
// update
|
||||
if($cdavdata['etag'] !== $etag)
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $httpbody
|
||||
]
|
||||
]);
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $httpbody
|
||||
]
|
||||
]);
|
||||
}
|
||||
else {
|
||||
// new
|
||||
@@ -235,7 +237,6 @@ class Cdav extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo);
|
||||
$carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
||||
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
||||
@@ -268,7 +269,7 @@ class Cdav extends Controller {
|
||||
|
||||
// Plugins
|
||||
$server->addPlugin(new \Sabre\DAV\Auth\Plugin($auth));
|
||||
//$server->addPlugin(new \Sabre\DAV\Browser\Plugin());
|
||||
// $server->addPlugin(new \Sabre\DAV\Browser\Plugin());
|
||||
$server->addPlugin(new \Sabre\DAV\Sync\Plugin());
|
||||
$server->addPlugin(new \Sabre\DAV\Sharing\Plugin());
|
||||
$server->addPlugin(new \Sabre\DAVACL\Plugin());
|
||||
@@ -276,7 +277,7 @@ class Cdav extends Controller {
|
||||
// CalDAV plugins
|
||||
$server->addPlugin(new \Sabre\CalDAV\Plugin());
|
||||
$server->addPlugin(new \Sabre\CalDAV\SharingPlugin());
|
||||
//$server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin());
|
||||
// $server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin());
|
||||
$server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
|
||||
|
||||
// CardDAV plugins
|
||||
|
||||
@@ -27,7 +27,7 @@ class Channel extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if (in_array(substr($_GET['search'], 0, 1), ['@', '!', '?']) || strpos($_GET['search'], 'https://') === 0)
|
||||
if (array_key_exists('search', $_GET) && (in_array(substr($_GET['search'], 0, 1), ['@', '!', '?']) || strpos($_GET['search'], 'https://') === 0))
|
||||
goaway(z_root() . '/search?f=&search=' . $_GET['search']);
|
||||
|
||||
$which = null;
|
||||
@@ -155,7 +155,7 @@ class Channel extends Controller {
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
opengraph_add_meta($r ? $r[0] : [], $channel);
|
||||
opengraph_add_meta((isset($r) && count($r) ? $r[0] : []), $channel);
|
||||
}
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
@@ -168,7 +168,7 @@ class Channel extends Controller {
|
||||
|
||||
if (strpos($mid, 'b64.') === 0)
|
||||
$decoded = @base64url_decode(substr($mid, 4));
|
||||
if ($decoded)
|
||||
if (isset($decoded))
|
||||
$mid = $decoded;
|
||||
|
||||
$datequery = ((x($_GET, 'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
|
||||
@@ -308,9 +308,9 @@ class Channel extends Controller {
|
||||
if (($update) && (!$load)) {
|
||||
|
||||
if ($mid) {
|
||||
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal_update
|
||||
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal_update
|
||||
AND item_wall = 1 $simple_update $sql_extra limit 1",
|
||||
dbesc($mid . '%'),
|
||||
dbesc($mid),
|
||||
intval(App::$profile['profile_uid'])
|
||||
);
|
||||
}
|
||||
@@ -328,6 +328,7 @@ class Channel extends Controller {
|
||||
}
|
||||
else {
|
||||
|
||||
$sql_extra2 = '';
|
||||
if (x($category)) {
|
||||
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY));
|
||||
}
|
||||
@@ -355,9 +356,9 @@ class Channel extends Controller {
|
||||
|
||||
if ($noscript_content || $load) {
|
||||
if ($mid) {
|
||||
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
|
||||
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal
|
||||
AND item_wall = 1 $sql_extra limit 1",
|
||||
dbesc($mid . '%'),
|
||||
dbesc($mid),
|
||||
intval(App::$profile['profile_uid'])
|
||||
);
|
||||
if (!$r) {
|
||||
@@ -419,7 +420,7 @@ class Channel extends Controller {
|
||||
|
||||
if ((!$update) && (!$load)) {
|
||||
|
||||
if ($decoded)
|
||||
if (isset($decoded))
|
||||
$mid = 'b64.' . base64url_encode($mid);
|
||||
|
||||
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
|
||||
@@ -485,7 +486,7 @@ class Channel extends Controller {
|
||||
|
||||
$o .= conversation($items, $mode, $update, $page_mode);
|
||||
|
||||
if ($mid && $items[0]['title'])
|
||||
if ($mid && count($items) > 0 && isset($items[0]['title']))
|
||||
App::$page['title'] = $items[0]['title'] . " - " . App::$page['title'];
|
||||
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class Channel_calendar extends Controller {
|
||||
|
||||
if ($results) {
|
||||
// Set permissions based on tag replacements
|
||||
set_linkified_perms($results, $str_contact_allow, $str_group_allow, $uid, false, $private);
|
||||
set_linkified_perms($results, $str_contact_allow, $str_group_allow, $uid, $private);
|
||||
|
||||
foreach ($results as $result) {
|
||||
$success = $result['success'];
|
||||
|
||||
@@ -123,7 +123,8 @@ class Cloud extends Controller {
|
||||
notice( t('Permission denied') . EOL);
|
||||
}
|
||||
elseif($err instanceof \Sabre\DAV\Exception\NotImplemented) {
|
||||
notice( t('Please refresh page') . EOL);
|
||||
// notice( t('Please refresh page') . EOL);
|
||||
goaway(z_root() . '/' . \App::$query_string);
|
||||
}
|
||||
else {
|
||||
notice( t('Unknown error') . EOL);
|
||||
|
||||
@@ -18,11 +18,11 @@ class Connect extends Controller {
|
||||
App::$error = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from channel where channel_address = '%s' limit 1",
|
||||
dbesc($which)
|
||||
);
|
||||
|
||||
|
||||
if($r)
|
||||
App::$data['channel'] = $r[0];
|
||||
|
||||
@@ -30,36 +30,36 @@ class Connect extends Controller {
|
||||
|
||||
profile_load($which,'');
|
||||
}
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
if(! array_key_exists('channel', App::$data))
|
||||
return;
|
||||
|
||||
$channel_id = App::$data['channel']['channel_id'];
|
||||
|
||||
$edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false);
|
||||
|
||||
|
||||
if($edit) {
|
||||
$has_premium = ((App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? 1 : 0);
|
||||
$premium = (($_POST['premium']) ? intval($_POST['premium']) : 0);
|
||||
$text = escape_tags($_POST['text']);
|
||||
|
||||
|
||||
if($has_premium != $premium) {
|
||||
$r = q("update channel set channel_pageflags = ( channel_pageflags %s %d ) where channel_id = %d",
|
||||
db_getfunc('^'),
|
||||
intval(PAGE_PREMIUM),
|
||||
intval(local_channel())
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','refresh_all',$channel_id));
|
||||
}
|
||||
set_pconfig($channel_id,'system','selltext',$text);
|
||||
// reload the page completely to get fresh data
|
||||
goaway(z_root() . '/' . App::$query_string);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
$url = '';
|
||||
$observer = App::get_observer();
|
||||
if(($observer) && ($_POST['submit'] === t('Continue'))) {
|
||||
@@ -70,18 +70,18 @@ class Connect extends Controller {
|
||||
dbesc($observer['xchan_hash'])
|
||||
);
|
||||
if($r)
|
||||
$url = $r[0]['hubloc_url'] . '/follow?f=&url=' . urlencode(channel_reddress(App::$data['channel']));
|
||||
$url = $r[0]['hubloc_url'] . '/follow?f=&interactive=1&url=' . urlencode(channel_reddress(App::$data['channel']));
|
||||
}
|
||||
}
|
||||
if($url)
|
||||
goaway($url . '&confirm=1');
|
||||
else
|
||||
notice('Unable to connect to your home hub location.');
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! array_key_exists('channel', App::$data))
|
||||
@@ -90,11 +90,11 @@ class Connect extends Controller {
|
||||
$channel_id = App::$data['channel']['channel_id'];
|
||||
|
||||
$edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false);
|
||||
|
||||
|
||||
$text = get_pconfig($channel_id,'system','selltext');
|
||||
|
||||
|
||||
if($edit) {
|
||||
|
||||
|
||||
$o = replace_macros(get_markup_template('sellpage_edit.tpl'),array(
|
||||
'$header' => t('Premium Channel Setup'),
|
||||
'$address' => App::$data['channel']['channel_address'],
|
||||
@@ -105,36 +105,36 @@ class Connect extends Controller {
|
||||
'$lbl2' => t('Potential connections will then see the following text before proceeding:'),
|
||||
'$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'),
|
||||
'$submit' => t('Submit'),
|
||||
|
||||
|
||||
|
||||
|
||||
));
|
||||
return $o;
|
||||
}
|
||||
else {
|
||||
if(! $text)
|
||||
$text = t('(No specific instructions have been provided by the channel owner.)');
|
||||
|
||||
|
||||
$submit = replace_macros(get_markup_template('sellpage_submit.tpl'), array(
|
||||
'$continue' => t('Continue'),
|
||||
'$continue' => t('Continue'),
|
||||
'$address' => App::$data['channel']['channel_address']
|
||||
));
|
||||
|
||||
|
||||
$o = replace_macros(get_markup_template('sellpage_view.tpl'),array(
|
||||
'$header' => t('Restricted or Premium Channel'),
|
||||
'$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'),
|
||||
'$text' => prepare_text($text),
|
||||
|
||||
'$text' => prepare_text($text),
|
||||
|
||||
'$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'),
|
||||
'$submit' => $submit,
|
||||
|
||||
|
||||
));
|
||||
|
||||
|
||||
$arr = array('channel' => App::$data['channel'],'observer' => App::get_observer(), 'sellpage' => $o, 'submit' => $submit);
|
||||
call_hooks('connect_premium', $arr);
|
||||
$o = $arr['sellpage'];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ class Directory extends Controller {
|
||||
$profile_link = chanlink_url($rr['url']);
|
||||
|
||||
$pdesc = (($rr['description']) ? $rr['description'] . '<br />' : '');
|
||||
$connect_link = ((local_channel()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : '');
|
||||
$connect_link = ((local_channel()) ? z_root() . '/follow?f=&interactive=1&url=' . urlencode($rr['address']) : '');
|
||||
|
||||
// Checking status is disabled ATM until someone checks the performance impact more carefully
|
||||
//$online = remote_online_status($rr['address']);
|
||||
|
||||
@@ -97,8 +97,8 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
if($decoded)
|
||||
$item_hash = $decoded;
|
||||
|
||||
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid like '%s' limit 1",
|
||||
dbesc($item_hash . '%')
|
||||
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid = '%s' limit 1",
|
||||
dbesc($item_hash)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
@@ -247,69 +247,62 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($noscript_content || $load) {
|
||||
|
||||
$r = null;
|
||||
|
||||
require_once('include/channel.php');
|
||||
$sys = get_sys_channel();
|
||||
$sysid = $sys['channel_id'];
|
||||
// in case somebody turned off public access to sys channel content using permissions
|
||||
// make that content unsearchable by ensuring the owner uid can't match
|
||||
$sys_id = perm_is_allowed($sys['channel_id'], $observer_hash, 'view_stream') ? $sys['channel_id'] : 0;
|
||||
|
||||
$r = null;
|
||||
|
||||
if(local_channel()) {
|
||||
$r = q("SELECT item.id as item_id from item WHERE uid = %d and mid = '%s' $item_normal limit 1",
|
||||
$r = q("SELECT item.id AS item_id FROM item WHERE uid = %d AND mid = '%s' $item_normal LIMIT 1",
|
||||
intval(local_channel()),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
}
|
||||
|
||||
if($r === null) {
|
||||
// in case somebody turned off public access to sys channel content using permissions
|
||||
// make that content unsearchable by ensuring the owner uid can't match
|
||||
|
||||
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
|
||||
$sysid = 0;
|
||||
|
||||
$r = q("SELECT item.id as item_id from item
|
||||
if(!$r) {
|
||||
$r = q("SELECT item.id AS item_id FROM item
|
||||
WHERE ((mid = '%s'
|
||||
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
|
||||
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
|
||||
AND item.deny_gid = '' AND item_private = 0 )
|
||||
and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
||||
AND uid IN ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
||||
OR uid = %d ))) OR
|
||||
(mid = '%s' $sql_extra ))
|
||||
$item_normal
|
||||
limit 1",
|
||||
dbesc($target_item['parent_mid']),
|
||||
intval($sysid),
|
||||
intval($sys_id),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
elseif($update && !$load) {
|
||||
$r = null;
|
||||
|
||||
require_once('include/channel.php');
|
||||
$sys = get_sys_channel();
|
||||
$sysid = $sys['channel_id'];
|
||||
// in case somebody turned off public access to sys channel content using permissions
|
||||
// make that content unsearchable by ensuring the owner uid can't match
|
||||
$sys_id = perm_is_allowed($sys['channel_id'], $observer_hash, 'view_stream') ? $sys['channel_id'] : 0;
|
||||
|
||||
$r = null;
|
||||
if(local_channel()) {
|
||||
$r = q("SELECT item.parent AS item_id from item
|
||||
WHERE uid = %d
|
||||
and parent_mid = '%s'
|
||||
AND parent_mid = '%s'
|
||||
$item_normal_update
|
||||
$simple_update
|
||||
limit 1",
|
||||
LIMIT 1",
|
||||
intval(local_channel()),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
}
|
||||
if($r === null) {
|
||||
// in case somebody turned off public access to sys channel content using permissions
|
||||
// make that content unsearchable by ensuring the owner_xchan can't match
|
||||
|
||||
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
|
||||
$sysid = 0;
|
||||
|
||||
if(! $r) {
|
||||
$r = q("SELECT item.id as item_id from item
|
||||
WHERE ((parent_mid = '%s'
|
||||
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
|
||||
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
|
||||
AND item.deny_gid = '' AND item_private = 0 )
|
||||
and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
||||
OR uid = %d ))) OR
|
||||
@@ -317,14 +310,14 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
$item_normal
|
||||
limit 1",
|
||||
dbesc($target_item['parent_mid']),
|
||||
intval($sysid),
|
||||
intval($sys_id),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
$r = array();
|
||||
$r = [];
|
||||
}
|
||||
|
||||
if($r) {
|
||||
@@ -332,7 +325,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
if($parents_str) {
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE parent in ( %s ) $item_normal ",
|
||||
WHERE parent in ( %s ) $sql_extra $item_normal ",
|
||||
dbesc($parents_str)
|
||||
);
|
||||
xchan_query($items);
|
||||
|
||||
@@ -14,7 +14,7 @@ use Zotlabs\Daemon\Master;
|
||||
class Follow extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
if (ActivityStreams::is_as_request() && argc() == 2) {
|
||||
|
||||
$abook_id = intval(argv(1));
|
||||
@@ -73,11 +73,11 @@ class Follow extends Controller {
|
||||
$url = notags(trim(punify($_REQUEST['url'])));
|
||||
$return_url = $_SESSION['return_url'];
|
||||
$confirm = intval($_REQUEST['confirm']);
|
||||
$interactive = (($_REQUEST['interactive']) ? intval($_REQUEST['interactive']) : 1);
|
||||
$interactive = (($_REQUEST['interactive']) ? intval($_REQUEST['interactive']) : 1);
|
||||
$channel = App::get_channel();
|
||||
|
||||
$result = Connect::connect($channel,$url);
|
||||
|
||||
|
||||
if ($result['success'] == false) {
|
||||
if ($result['message']) {
|
||||
notice($result['message']);
|
||||
@@ -89,9 +89,9 @@ class Follow extends Controller {
|
||||
json_return_and_die($result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
info( t('Connection added.') . EOL);
|
||||
|
||||
|
||||
$clone = array();
|
||||
foreach ($result['abook'] as $k => $v) {
|
||||
if (strpos($k,'abook_') === 0) {
|
||||
@@ -101,30 +101,30 @@ class Follow extends Controller {
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
|
||||
if ($abconfig) {
|
||||
$clone['abconfig'] = $abconfig;
|
||||
}
|
||||
Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true);
|
||||
|
||||
|
||||
$can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream');
|
||||
|
||||
|
||||
// If we can view their stream, pull in some posts
|
||||
|
||||
|
||||
if (($can_view_stream) || ($result['abook']['xchan_network'] === 'rss')) {
|
||||
Master::Summon([ 'Onepoll', $result['abook']['abook_id'] ]);
|
||||
}
|
||||
|
||||
|
||||
if ($interactive) {
|
||||
goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1');
|
||||
}
|
||||
else {
|
||||
json_return_and_die([ 'success' => true ]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
if (! local_channel()) {
|
||||
return login();
|
||||
|
||||
@@ -41,7 +41,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
if(argc() > 1 && argv(1) !== 'load') {
|
||||
$item_hash = argv(1);
|
||||
}
|
||||
|
||||
|
||||
if($_REQUEST['mid'])
|
||||
$item_hash = $_REQUEST['mid'];
|
||||
|
||||
@@ -49,9 +49,9 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
$item_normal_update = item_normal_update();
|
||||
|
||||
if(! $item_hash) {
|
||||
$r = q("SELECT mid FROM item
|
||||
$r = q("SELECT mid FROM item
|
||||
WHERE uid = %d $item_normal
|
||||
AND mid = parent_mid
|
||||
AND mid = parent_mid
|
||||
ORDER BY created DESC LIMIT 1",
|
||||
intval(local_channel())
|
||||
);
|
||||
@@ -71,10 +71,10 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
$target_item = null;
|
||||
|
||||
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid like '%s' limit 1",
|
||||
dbesc($item_hash . '%')
|
||||
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid = '%s' limit 1",
|
||||
dbesc($item_hash)
|
||||
);
|
||||
|
||||
|
||||
if($r) {
|
||||
$target_item = $r[0];
|
||||
}
|
||||
@@ -83,7 +83,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
if($target_item['item_blocked'] == ITEM_MODERATED) {
|
||||
goaway(z_root() . '/moderate/' . $target_item['id']);
|
||||
}
|
||||
|
||||
|
||||
$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']) . "' ) ";
|
||||
@@ -94,16 +94,16 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
$sys_item = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(! $update) {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$channel_acl = [
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'deny_gid' => $channel['channel_deny_gid']
|
||||
];
|
||||
];
|
||||
|
||||
$x = [
|
||||
'is_owner' => true,
|
||||
@@ -143,7 +143,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
// if the target item is not a post (eg a like) we want to address its thread parent
|
||||
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
$mid = $target_item['mid'];
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
if($decoded)
|
||||
$mid = 'b64.' . base64url_encode($mid);
|
||||
}
|
||||
@@ -154,7 +154,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
$o .= '<div id="live-hq"></div>' . "\r\n";
|
||||
$o .= "<script> var profile_uid = " . local_channel()
|
||||
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . ";</script>\r\n";
|
||||
|
||||
|
||||
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[
|
||||
'$baseurl' => z_root(),
|
||||
'$pgtype' => 'hq',
|
||||
@@ -241,14 +241,14 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
$r = [];
|
||||
}
|
||||
|
||||
|
||||
if($r) {
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE parent = '%s' $item_normal ",
|
||||
dbesc($r[0]['item_id'])
|
||||
);
|
||||
|
||||
|
||||
xchan_query($items,true,(($sys_item) ? local_channel() : 0));
|
||||
$items = fetch_post_tags($items,true);
|
||||
$items = conv_sort($items,'created');
|
||||
|
||||
@@ -209,12 +209,6 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
|
||||
logger('import step 3');
|
||||
|
||||
if(is_array($data['hubloc'])) {
|
||||
import_hublocs($channel,$data['hubloc'],$seize,$moving);
|
||||
}
|
||||
|
||||
logger('import step 4');
|
||||
|
||||
// create new hubloc for the new channel at this site
|
||||
|
||||
if(array_key_exists('channel',$data)) {
|
||||
@@ -277,7 +271,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
logger('import step 5');
|
||||
logger('import step 4');
|
||||
|
||||
|
||||
// import xchans and contact photos
|
||||
@@ -335,7 +329,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
logger('import step 6');
|
||||
logger('import step 5');
|
||||
|
||||
// import xchans
|
||||
$xchans = $data['xchan'];
|
||||
@@ -404,7 +398,14 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
logger('import step 7');
|
||||
logger('import step 6');
|
||||
}
|
||||
|
||||
logger('import step 7');
|
||||
|
||||
// this must happen after xchans got imported!
|
||||
if(is_array($data['hubloc'])) {
|
||||
import_hublocs($channel,$data['hubloc'],$seize,$moving);
|
||||
}
|
||||
|
||||
$friends = 0;
|
||||
|
||||
@@ -6,7 +6,7 @@ use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
/**
|
||||
* module: invite.php
|
||||
* module: invitexv2.php
|
||||
*
|
||||
* send email invitations to join social network
|
||||
*
|
||||
@@ -15,91 +15,291 @@ use Zotlabs\Web\Controller;
|
||||
|
||||
class Invite extends Controller {
|
||||
|
||||
/**
|
||||
* While coding this, I want to introduce a system of qualified messages and notifications.
|
||||
* Each message consists of a 3 letter prefix, a 4 digit number and a one letter suffix (PREnnnnS).
|
||||
* The spirit about is not from me, but many decades used by IBM inc. in devel with best success.
|
||||
*
|
||||
* The system prefix, used uppercase as system message id, lowercase as css and js prefix (classes, ids etc).
|
||||
* Usually not used as self::MYP, but placed in the code dominant enough for easy to find.
|
||||
*
|
||||
* Concrete here:
|
||||
* The prefix indicates Z for the Zlabs(core), A for Account stuff, I for Invite.
|
||||
* The numbers scope will be 00xx within/for templates, 01xx for get, 02xx for post functions.
|
||||
* Message qualification ends with a uppercase suffix, where
|
||||
* I=Info(only),
|
||||
* W=Warning(more then info and less then error),
|
||||
* E=Error,
|
||||
* F=Fatal(for unexpected errors).
|
||||
* Btw, in case of using fail2ban, a scan of messages going to log is very much more with ease,
|
||||
* esspecially in multi language driven systems where messages vary.
|
||||
*
|
||||
* @author Hilmar Runge
|
||||
* @version 2.0.0
|
||||
* @since 2020-01-20
|
||||
*
|
||||
*/
|
||||
|
||||
const MYP = 'ZAI';
|
||||
const VERSION = '2.0.0';
|
||||
|
||||
function post() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
|
||||
// zai02
|
||||
|
||||
if (! local_channel()) {
|
||||
notice( 'ZAI0201E,' .t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Invite')) {
|
||||
if (! Apps::system_app_installed(local_channel(), 'Invite')) {
|
||||
notice( 'ZAI0202E,' . t('Invite App') . ' (' . t('Not Installed') . ')' . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
check_form_security_token_redirectOnErr('/', 'send_invite');
|
||||
|
||||
$max_invites = intval(get_config('system','max_invites'));
|
||||
if(! $max_invites)
|
||||
$max_invites = 50;
|
||||
|
||||
$current_invites = intval(get_pconfig(local_channel(),'system','sent_invites'));
|
||||
if($current_invites > $max_invites) {
|
||||
notice( t('Total invitation limit exceeded.') . EOL);
|
||||
|
||||
$ok = $ko = 0;
|
||||
$feedbk = '';
|
||||
$isajax = is_ajax();
|
||||
$eol = $isajax ? "\n" : EOL;
|
||||
$policy = intval(get_config('system','register_policy'));
|
||||
if ($policy == REGISTER_CLOSED) {
|
||||
notice( 'ZAI0212E,' . t('Register is closed') . ')' . EOL);
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
$recips = ((x($_POST,'recipients')) ? explode("\n",$_POST['recipients']) : array());
|
||||
$message = ((x($_POST,'message')) ? notags(trim($_POST['message'])) : '');
|
||||
|
||||
$total = 0;
|
||||
|
||||
if(get_config('system','invitation_only')) {
|
||||
$invonly = true;
|
||||
$x = get_pconfig(local_channel(),'system','invites_remaining');
|
||||
if((! $x) && (! is_site_admin()))
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($recips as $recip) {
|
||||
|
||||
$recip = trim($recip);
|
||||
if(! $recip)
|
||||
continue;
|
||||
|
||||
if(! validate_email($recip)) {
|
||||
notice( sprintf( t('%s : Not a valid email address.'), $recip) . EOL);
|
||||
continue;
|
||||
}
|
||||
|
||||
else
|
||||
$nmessage = $message;
|
||||
|
||||
$account = App::get_account();
|
||||
|
||||
$res = z_mail(
|
||||
[
|
||||
'toEmail' => $recip,
|
||||
'fromName' => ' ',
|
||||
'fromEmail' => $account['account_email'],
|
||||
'messageSubject' => t('Please join us on $Projectname'),
|
||||
'textVersion' => $nmessage,
|
||||
]
|
||||
);
|
||||
|
||||
if($res) {
|
||||
$total ++;
|
||||
$current_invites ++;
|
||||
set_pconfig(local_channel(),'system','sent_invites',$current_invites);
|
||||
if($current_invites > $max_invites) {
|
||||
notice( t('Invitation limit exceeded. Please contact your site administrator.') . EOL);
|
||||
return;
|
||||
if ($policy == REGISTER_OPEN)
|
||||
$flags = 0;
|
||||
elseif ($policy == REGISTER_APPROVE)
|
||||
$flags = ACCOUNT_PENDING;
|
||||
$flags = ($flags | intval(get_config('system','verify_email')));
|
||||
|
||||
// how many max recipients in one mail submit
|
||||
$maxto = get_config('system','invitation_max_recipients', 'na');
|
||||
If (is_site_admin()) {
|
||||
// set, if admin is operator, default to 12
|
||||
if ($maxto === 'na') set_config('system','invitation_max_recipients', 12);
|
||||
}
|
||||
$maxto = ($maxto === 'na') ? 12 : $maxto;
|
||||
|
||||
// language code current for the invitation
|
||||
$lcc = x($_POST['zailcc']) && preg_match('/[a-z\-]{2,5}/', $_POST['zailcc'])
|
||||
? $_POST['zailcc']
|
||||
: '';
|
||||
|
||||
// expiration duration amount quantity, in case of doubts defaults 2
|
||||
$durn = x($_POST['zaiexpiren']) && preg_match('/[0-9]{1,2}/', $_POST['zaiexpiren'])
|
||||
? trim(intval($_POST['zaiexpiren']))
|
||||
: '2';
|
||||
!$durn ? $durn = 2 : '';
|
||||
|
||||
// expiration duration unit 1st letter (day, weeks, months, years), defaults days
|
||||
$durq = x($_POST['zaiexpire']) && preg_match('/[ihd]{1,1}/', $_POST['zaiexpire'])
|
||||
? $_POST['zaiexpire']
|
||||
: 'd';
|
||||
|
||||
$dur = self::calcdue($durn.$durq);
|
||||
$due = t('Note, the invitation code is valid up to') . ' ' . $dur['due'];
|
||||
|
||||
if ($isajax) {
|
||||
$feedbk .= 'ZAI0207I ' . $due . $eol;
|
||||
}
|
||||
|
||||
// take the received email addresses and discart duplicates
|
||||
$recips = array_filter( array_unique( preg_replace('/^\s*$/', '',
|
||||
((x($_POST,'zaito')) ? explode( "\n",$_POST['zaito']) : array() ) )));
|
||||
|
||||
$havto = count($recips);
|
||||
|
||||
if ( $havto > $maxto) {
|
||||
$feedbk .= 'ZAI0210E ' . sprintf( t('Too many recipients for one invitation (max %d)'), $maxto) . $eol;
|
||||
$ko++;
|
||||
|
||||
} elseif ( $havto == 0 ) {
|
||||
$feedbk .= 'ZAI0211E ' . t('No recipients for this invitation') . $eol;
|
||||
$ko++;
|
||||
|
||||
} else {
|
||||
|
||||
// each email address
|
||||
foreach($recips as $n => $recip) {
|
||||
|
||||
// if empty ignore
|
||||
$recip = $recips[$n] = trim($recip);
|
||||
if(! $recip) continue;
|
||||
|
||||
// see if we have an email address who@domain.tld
|
||||
if (!preg_match('/^.{2,64}\@[a-z0-9.-]{4,32}\.[a-z]{2,12}$/', $recip)) {
|
||||
$feedbk .= 'ZAI0203E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a valid email address'), $recip) . $eol;
|
||||
$ko++;
|
||||
continue;
|
||||
}
|
||||
if(! validate_email($recip)) {
|
||||
$feedbk .= 'ZAI0204E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a real email address'), $recip) . $eol;
|
||||
$ko++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// do we accept the email (not black listed)
|
||||
if(! allowed_email($recip)) {
|
||||
$feedbk .= 'ZAI0205E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not allowed email address'), $recip) . $eol;
|
||||
$ko++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// is the email address just in use for account or registered before
|
||||
$r = q("SELECT account_email AS em FROM account WHERE account_email = '%s'"
|
||||
. " UNION "
|
||||
."SELECT reg_email AS em FROM register WHERE reg_vital = 1 AND reg_email = '%s' LIMIT 1;",
|
||||
dbesc($recip),
|
||||
dbesc($recip)
|
||||
);
|
||||
if($r && $r[0]['em'] == $recip) {
|
||||
$feedbk .= 'ZAI0206E ' . ($n+1) . ': ' . sprintf( t('(%s) : email address already in use'), $recip) . $eol;
|
||||
$ko++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($isajax) {
|
||||
// seems we have an email address acceptable
|
||||
$feedbk .= 'ZAI0209I ' . ($n+1) . ': ' . sprintf( t('(%s) : Accepted email address'), $recip) . $eol;
|
||||
}
|
||||
}
|
||||
else {
|
||||
notice( sprintf( t('%s : Message delivery failed.'), $recip) . EOL);
|
||||
}
|
||||
|
||||
}
|
||||
notice( sprintf( tt("%d message sent.", "%d messages sent.", $total) , $total) . EOL);
|
||||
|
||||
if ($isajax) {
|
||||
// we are not silent on the ajax road
|
||||
echo json_encode(array('feedbk' => $feedbk, 'due' => $due));
|
||||
|
||||
// that mission is complete
|
||||
killme();
|
||||
exit;
|
||||
}
|
||||
|
||||
// Total ?todo notice( t('Invitation limit exceeded. Please contact your site administrator.') . EOL);
|
||||
|
||||
// any errors up to now in fg?
|
||||
|
||||
|
||||
// down from here, only on the main road (no more ajax)
|
||||
|
||||
// tell if sth is to tell
|
||||
$feedbk ? notice($feedbk) . $eol : '';
|
||||
|
||||
if ($ko > 0) return;
|
||||
|
||||
// the personal mailtext
|
||||
$mailtext = ((x($_POST,'zaitxt')) ? notags(trim($_POST['zaitxt'])) : '');
|
||||
|
||||
// to log in db
|
||||
$reonar = json_decode( ((x($_POST,'zaireon')) ? notags(trim($_POST['zaireon'])) : ''), TRUE, 8) ;
|
||||
|
||||
// me, the invitor
|
||||
$account = App::get_account();
|
||||
$reonar['from'] = $account['account_email'];
|
||||
$reonar['date'] = datetime_convert();
|
||||
$reonar['fromip'] = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
// who is the invitor on
|
||||
$inby = local_channel();
|
||||
|
||||
$ok = $ko = 0;
|
||||
|
||||
// send the mail(s)
|
||||
foreach($recips as $n => $recip) {
|
||||
|
||||
$reonar['due'] = $due;
|
||||
$reonar['to'] = $recip;
|
||||
$reonar['txtpersonal'] = $mailtext;
|
||||
|
||||
// generate an invide code to store and pm
|
||||
$invite_code = autoname(8) . rand(1000,9999);
|
||||
|
||||
// again the final localized templates $reonar['subject'] $reonar['lang'] $reonar['tpl']
|
||||
|
||||
// save current operators lc and take the desired to mail
|
||||
push_lang($reonar['lang']);
|
||||
// resolve
|
||||
$tx = replace_macros(get_intltext_template('invite.'.$reonar['tpl'].'.tpl'),
|
||||
array(
|
||||
'$projectname' => t('$Projectname'),
|
||||
'$invite_code' => $invite_code,
|
||||
'$invite_where' => z_root() . '/register',
|
||||
'$invite_whereami' => str_replace('@', '@+', $reonar['whereami']),
|
||||
'$invite_whoami' => z_root() . '/channel/' . $reonar['whoami'],
|
||||
'$invite_anywhere' => z_root() . '/pubsites'
|
||||
)
|
||||
);
|
||||
// restore lc to operator
|
||||
pop_lang();
|
||||
|
||||
$reonar['txttemplate'] = $tx;
|
||||
|
||||
// pm
|
||||
$zem = z_mail(
|
||||
[
|
||||
'toEmail' => $recip,
|
||||
'fromName' => ' ',
|
||||
'fromEmail' => $reonar['from'],
|
||||
'messageSubject' => $reonar['subject'],
|
||||
'textVersion' => ($mailtext ? $mailtext . "\n\n" : '') . $tx . "\n" . $due,
|
||||
]
|
||||
);
|
||||
|
||||
if(!$zem) {
|
||||
|
||||
$ko++;
|
||||
$msg = 'ZAI0208E,' . sprintf( t('%s : Message delivery failed.'), $recip);
|
||||
|
||||
} else {
|
||||
|
||||
$ok++;
|
||||
$msg = 'ZAI0208I ' . sprintf( t('To %s : Message delivery success.'), $recip);
|
||||
|
||||
// if verify_email is the rule, email becomes a dId2 - NO
|
||||
// $did2 = ($flags & ACCOUNT_UNVERIFIED) == ACCOUNT_UNVERIFIED ? $recip : '';
|
||||
|
||||
// always enforce verify email with invitations, thus email becomes a dId2
|
||||
$did2 = $recip;
|
||||
$flags |= ACCOUNT_UNVERIFIED;
|
||||
|
||||
// defaults vital, reg_pass
|
||||
$r = q("INSERT INTO register ("
|
||||
. "reg_flags,reg_didx,reg_did2,reg_hash,reg_created,reg_startup,reg_expires,reg_email,reg_byc,reg_uid,reg_atip,reg_lang,reg_stuff)"
|
||||
. " VALUES ( %d, 'i', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s') ",
|
||||
intval($flags),
|
||||
dbesc($did2),
|
||||
dbesc($invite_code),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($dur['due']),
|
||||
dbesc($recip),
|
||||
intval($inby),
|
||||
intval($account['account_id']),
|
||||
dbesc($reonar['fromip']),
|
||||
dbesc($reonar['lang']),
|
||||
dbesc(json_encode( array('reon' => $reonar) ))
|
||||
);
|
||||
}
|
||||
$msg .= ' (a' . $account['account_id'] . ', c' . $inby . ', from:' . $reonar['from'] . ')';
|
||||
zar_log( $msg);
|
||||
}
|
||||
|
||||
$ok + $ko > 0
|
||||
? notice( 'ZAI0212I ' . sprintf( t('%1$d mail(s) sent, %2$d mail error(s)'), $ok, $ko) . EOL)
|
||||
: '';
|
||||
//logger( print_r( $reonar, true) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
// zai1
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
notice( 'ZAI0101E,' . t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -107,68 +307,267 @@ class Invite extends Controller {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
|
||||
$o = '<b>' . t('Invite App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||
$o .= t('Send email invitations to join this network');
|
||||
$o = 'ZAI0102E,' . t('Invite App') . ' (' . t('Not Installed') . ')' . EOL;
|
||||
return $o;
|
||||
}
|
||||
|
||||
nav_set_selected('Invite');
|
||||
|
||||
$tpl = get_markup_template('invite.tpl');
|
||||
$invonly = false;
|
||||
|
||||
if(get_config('system','invitation_only')) {
|
||||
$invonly = true;
|
||||
$x = get_pconfig(local_channel(),'system','invites_remaining');
|
||||
if((! $x) && (! is_site_admin())) {
|
||||
notice( t('You have no more invitations available') . EOL);
|
||||
if (! (get_config('system','invitation_also') || get_config('system','invitation_only')) ) {
|
||||
$o = 'ZAI0103E,' . t('Invites not proposed by configuration') . '. ';
|
||||
$o .= t('Contact the site admin');
|
||||
return $o;
|
||||
}
|
||||
|
||||
// invitation_by_user may still not configured, the default 'na' will tell this
|
||||
// if configured, 0 disables invitations by users, other numbers are how many invites a user may propagate
|
||||
$invuser = get_config('system','invitation_by_user', 'na');
|
||||
|
||||
// if the mortal user drives the invitation
|
||||
If (! is_site_admin()) {
|
||||
|
||||
// when not configured, 4 is the default
|
||||
$invuser = ($invuser === 'na') ? 4 : $invuser;
|
||||
|
||||
// a config value 0 disables invitation by users
|
||||
if (!$invuser) {
|
||||
$o = 'ZAI0104E, ' . t('Invites by users not enabled') . '. ';
|
||||
return $o;
|
||||
}
|
||||
|
||||
if ($ihave >= $invuser) {
|
||||
notice( 'ZAI0105W,' . t('You have no more invitations available') . EOL);
|
||||
return '';
|
||||
}
|
||||
|
||||
} else {
|
||||
// general deity admin invite limit infinite (theoretical)
|
||||
if ($invuser === 'na') set_config('system','invitation_by_user', 4);
|
||||
// for display only
|
||||
$invuser = '∞';
|
||||
}
|
||||
|
||||
if($invonly && ($x || is_site_admin())) {
|
||||
$invite_code = autoname(8) . rand(1000,9999);
|
||||
$nmessage = str_replace('$invite_code',$invite_code,$message);
|
||||
|
||||
$r = q("INSERT INTO register (hash,created,uid,password,lang) VALUES ('%s', '%s',0,'','') ",
|
||||
dbesc($invite_code),
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
|
||||
if(! is_site_admin()) {
|
||||
$x --;
|
||||
if($x >= 0)
|
||||
set_pconfig(local_channel(),'system','invites_remaining',$x);
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// xchan record of the page observer
|
||||
// while quoting matters the user, the sending is associated with a channel (of the user)
|
||||
// also the admin may and should decide, which channel will told to the public
|
||||
$ob = App::get_observer();
|
||||
if(! $ob)
|
||||
return $o;
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
return 'ZAI0109F,' . t('Not on xchan') . EOL;
|
||||
$whereami = $ob['xchan_addr'];
|
||||
$channel = App::get_channel();
|
||||
$whoami = $channel['channel_address'];
|
||||
|
||||
// to pass also to post()
|
||||
$tao = 'tao.zai.whereami = ' . "'" . $whereami . "';\n"
|
||||
. 'tao.zai.whoami = ' . "'" . $whoami . "';\n";
|
||||
|
||||
// expirations, duration interval
|
||||
$dur = self::calcdue();
|
||||
$tao .= 'tao.zai.expire = { durn: ' . $dur['durn']
|
||||
. ', durq: ' . "'" . $dur['durq'] . "'"
|
||||
. ', due: ' . "'" . $dur['due'] . "' };\n";
|
||||
|
||||
// to easy redisplay the empty form
|
||||
nav_set_selected('Invite');
|
||||
|
||||
// inform about the count of invitations we have at all
|
||||
$r = q("SELECT count(reg_id) as ct FROM register WHERE reg_vital = 1"); // where not admin TODO
|
||||
$wehave = ($r ? $r[0]['ct'] : 0);
|
||||
|
||||
// invites max for all users except admins
|
||||
$invmaxau = intval(get_config('system','invitations_max_users'));
|
||||
if(! $invmaxau) {
|
||||
$invmaxau = 50;
|
||||
if (is_site_admin()) {
|
||||
set_config('system','invitations_max_users',intval($invmaxau));
|
||||
}
|
||||
}
|
||||
|
||||
if ($wehave > $invmaxau) {
|
||||
if (! is_site_admin()) {
|
||||
$feedbk .= 'ZAI0200E,' . t('All users invitation limit exceeded.') . $eol;
|
||||
}
|
||||
}
|
||||
|
||||
// let see how many invites currently used by the user
|
||||
$r = q("SELECT count(reg_id) AS n FROM register WHERE reg_vital = 1 AND reg_byc = %d",
|
||||
intval(local_channel()));
|
||||
$ihave = $r ? $r[0]['n'] : 0;
|
||||
|
||||
$tpl = get_markup_template('invite.tpl');
|
||||
|
||||
$inv_rabots = array(
|
||||
'i' => t('Minute(s)'),
|
||||
'h' => t('Hour(s)') ,
|
||||
'd' => t('Day(s)')
|
||||
);
|
||||
$inv_expire = replace_macros(get_markup_template('field_duration.qmc.tpl'),
|
||||
array(
|
||||
'label' => t('Invitation expires after'),
|
||||
'qmc' => 'zai',
|
||||
'qmcid' => 'ZAI0014I',
|
||||
'field' => array(
|
||||
'name' => 'expire',
|
||||
'title' => t('duration up from now'),
|
||||
'value' => ($invexpire_n ? $invexpire_n : 2),
|
||||
'min' => '1',
|
||||
'max' => '99',
|
||||
'size' => '2',
|
||||
'default' => ($invexpire_u ? $invexpire_u : 'd')
|
||||
),
|
||||
'rabot' => $inv_rabots
|
||||
)
|
||||
);
|
||||
|
||||
// let generate an invite code that here and never will be applied (only to fill displayed template)
|
||||
// real invite codes become generated for each recipient when we store the new invitation(s)
|
||||
// $invite_code = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 8) . rand(1000,9999);
|
||||
// let take one descriptive for template (as said is never used)
|
||||
$invite_code = 'INVITATE2020';
|
||||
|
||||
// what languages we use now
|
||||
$lccmy = ((isset(App::$config['system']['language'])) ? App::$config['system']['language'] : 'en');
|
||||
// and all the localized templates belonging to invite
|
||||
$tpls = glob('view/*/invite.*.tpl');
|
||||
|
||||
$tpla=$tplx=$tplxs=array();
|
||||
foreach ($tpls as $tpli) {
|
||||
list( $nop, $l, $t ) = explode( '/', $tpli);
|
||||
if ( preg_match('/\.subject/', $t) =='1' ) {
|
||||
// indicate a subject tpl exists
|
||||
$t=str_replace(array('invite.', '.subject', '.tpl'), '', $t);
|
||||
$tplxs[$l][$t]=true;
|
||||
continue;
|
||||
}
|
||||
// collect unique template names cross all languages and
|
||||
// tpla[language][]=template those available in each language
|
||||
$tplx[] = $tpla[$l][] = str_replace( array('invite.', '.tpl'), '', $t);
|
||||
}
|
||||
|
||||
$langs = array_keys($tpla);
|
||||
asort($langs);
|
||||
|
||||
$tplx = array_unique($tplx);
|
||||
asort($tplx);
|
||||
|
||||
// prepare current language and the default standard template (causual) for js
|
||||
// With and in js, I use a var 'tao' as a shortcut for top array object
|
||||
// and also qualify the object with the prefix zai = tao.zai as my var used outsite functions
|
||||
// can be unique within the overall included spaghette whirls
|
||||
// one can say Im too lazy to write prototypes and just I can agree.
|
||||
// tao simply applies the fact of using the same var as object and/or array in ja.
|
||||
$tao.='tao.zai.lccmy = ' . "'" . $lccmy . "';\n" . 'tao.zai.itpl = ' . "'" . 'casual' . "';\n";
|
||||
|
||||
$lcclane=$tx=$tplin='';
|
||||
//$lccsym='<span class="fa zai_fa zai_lccsym"></span>'; // alt
|
||||
$tplsym='<span class="fa zai_fa"></span>';
|
||||
|
||||
// I will uncomment for js console debug
|
||||
// $tao.='tao.zai.debug = ' . "'" . json_encode($tplxs) . "';\n";
|
||||
|
||||
// running thru the localized templates (subjects and textmsgs) and bring them to tao
|
||||
// lcc LanguageCountryCode,
|
||||
// lcc2 is a 2 character and lcc5 a 5 character LanguageCountryCode
|
||||
foreach($tpla as $l => $tn) {
|
||||
|
||||
// restyle lc to iso getttext format to avoid errors in js, hilite the current
|
||||
$lcc = str_replace('-', '_', $l);
|
||||
$hi = ($l == $lccmy) ? ' zai_hi' : '';
|
||||
$lcc2 = strlen($l) == 2 ? ' zai_lcc2' : '';
|
||||
$lcc5 = strlen($l) == 5 ? ' zai_lcc5' : '';
|
||||
$lccg = ' zai_lccg' . substr( $l, 0, 2 );
|
||||
$lcclane
|
||||
.= '<span class="fa zai_fa zai_lccsym' . $lcc2 . $lcc5 . $lccg . '"></span>'
|
||||
. '<a href="javascript:;" class="zai_lcc' . $lcc2 . $lcc5 . $lccg . $hi . '">' . $lcc . '</a>';
|
||||
// textmsg
|
||||
$tao .= 'tao.zai.t.' . $lcc . ' = {};' . "\n";
|
||||
// subject
|
||||
$tao .= 'tao.zai.s.' . $lcc . ' = {};' . "\n";
|
||||
|
||||
// resolve localized templates and take intented lc for
|
||||
foreach($tn as $t1) {
|
||||
|
||||
// save current lc and take the desired
|
||||
push_lang($l);
|
||||
|
||||
// resolve
|
||||
$tx = replace_macros(get_intltext_template('invite.'.$t1.'.tpl'),
|
||||
array(
|
||||
'$projectname' => t('$Projectname'),
|
||||
'$invite_code' => $invite_code,
|
||||
'$invite_where' => z_root() . '/register',
|
||||
'$invite_whereami' => $whereami,
|
||||
'$invite_whoami' => z_root() . '/channel/' . $whoami,
|
||||
'$invite_anywhere' => z_root() . '/pubsites'
|
||||
)
|
||||
);
|
||||
|
||||
// a default subject if no associated exists
|
||||
$ts=t('Invitation');
|
||||
if ( $tplxs[$l][$t1] )
|
||||
$ts = replace_macros(get_intltext_template('invite.'.$t1.'.subject.tpl'),
|
||||
array(
|
||||
'$projectname' => t('$Projectname'),
|
||||
'$invite_loc' => get_config('system','sitename')
|
||||
)
|
||||
);
|
||||
|
||||
// restore lc to current foreground
|
||||
pop_lang();
|
||||
|
||||
// bring to tao as js like it
|
||||
$tao .= 'tao.zai.t.' . $lcc . '.' . $t1 . " = '" . rawurlencode($tx) . "';\n";
|
||||
$tao .= 'tao.zai.s.' . $lcc . '.' . $t1 . " = '" . rawurlencode($ts) . "';\n";
|
||||
}
|
||||
}
|
||||
|
||||
// hilite the current defauls just from the beginning
|
||||
foreach ($tplx as $t1) {
|
||||
$hi = ($t1 == 'casual') ? ' zai_hi' : '';
|
||||
$tplin .= $tplsym.'<a href="javascript:;" id="zai-' . $t1
|
||||
. '" class="invites'.$hi.'">' . $t1 . '</a>';
|
||||
}
|
||||
|
||||
// fill the form for foreground
|
||||
$o = replace_macros($tpl, array(
|
||||
'$form_security_token' => get_form_security_token("send_invite"),
|
||||
'$zai' => strtolower(self::MYP),
|
||||
'$tao' => $tao,
|
||||
'$invite' => t('Send invitations'),
|
||||
'$addr_text' => t('Enter email addresses, one per line:'),
|
||||
'$msg_text' => t('Your message:'),
|
||||
'$default_message' => t('Please join my community on $Projectname.') . "\r\n" . "\r\n"
|
||||
. $linktxt
|
||||
. (($invonly) ? "\r\n" . "\r\n" . t('You will need to supply this invitation code:') . " " . $invite_code . "\r\n" . "\r\n" : '')
|
||||
. t('1. Register at any $Projectname location (they are all inter-connected)')
|
||||
. "\r\n" . "\r\n" . z_root() . '/register'
|
||||
. "\r\n" . "\r\n" . t('2. Enter my $Projectname network address into the site searchbar.')
|
||||
. "\r\n" . "\r\n" . $ob['xchan_addr'] . ' (' . t('or visit') . " " . z_root() . '/channel/' . $channel['channel_address'] . ')'
|
||||
. "\r\n" . "\r\n"
|
||||
. t('3. Click [Connect]')
|
||||
. "\r\n" . "\r\n" ,
|
||||
'$ihave' => 'ZAI0106I, ' . t('Invitations I am using') . ': ' . $ihave . ' / ' . $invuser,
|
||||
'$wehave' => 'ZAI0107I, ' . t('Invitations we are using') . ': ' . $wehave . ' / ' . $invmaxau,
|
||||
'$n10' => 'ZAI0010I', '$m10' => t('§ Note, the email(s) sent will be recorded in the system logs'),
|
||||
'$n11' => 'ZAI0011I', '$m11' => t('Enter email addresses, one per line:'),
|
||||
'$n12' => 'ZAI0012I', '$m12' => t('Your message:'),
|
||||
'$n13' => 'ZAI0013I', '$m13' => t('Invite template'),
|
||||
'$inv_expire' => $inv_expire,
|
||||
'$subject_label' => t('Subject:'),
|
||||
'$subject' => t('Invitation'),
|
||||
'$lcclane' => $lcclane,
|
||||
'$tplin' => $tplin,
|
||||
'$standard_message' => '',
|
||||
'$personal_message' => '',
|
||||
'$personal_pointer' => t('Here you may enter personal notes to the recipient(s)'),
|
||||
'$due' => t('Note, the invitation code is valid up to') . ' ' . $dur['due'],
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
function calcdue($duri=false) {
|
||||
// expirations, duration interval
|
||||
if ($duri===false)
|
||||
$duri = get_config('system','register_expire', '2d');
|
||||
if ( preg_match( '/^[0-9]{1,2}[ihdwmy]{1}$/', $duri ) ) {
|
||||
$durq = substr($duri, -1);
|
||||
$durn = substr($duri, 0, -1);
|
||||
$due = date('Y-m-d H:i:s', strtotime('+' . $durn . ' '
|
||||
. str_replace( array(':i',':h',':d',':w',':m',':y'),
|
||||
array('minutes', 'hours', 'days', 'weeks', 'months', 'years'),
|
||||
(':'.$durq))
|
||||
));
|
||||
return array( 'durn' => $durn, 'durq' => $durq, 'due' => $due);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -840,7 +840,7 @@ class Item extends Controller {
|
||||
if($results) {
|
||||
|
||||
// Set permissions based on tag replacements
|
||||
set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item, $private);
|
||||
set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item);
|
||||
|
||||
foreach($results as $result) {
|
||||
$success = $result['success'];
|
||||
|
||||
@@ -20,8 +20,10 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?']) || strpos($_GET['search'], 'https://') === 0)
|
||||
goaway(z_root() . '/search?f=&search=' . $_GET['search']);
|
||||
$search = $_GET['search'] ?? '';
|
||||
|
||||
if(in_array(substr($search, 0, 1),[ '@', '!', '?']) || strpos($search, 'https://') === 0)
|
||||
goaway(z_root() . '/search?f=&search=' . $search);
|
||||
|
||||
if(count($_GET) < 2) {
|
||||
$network_options = get_pconfig(local_channel(),'system','network_page_default');
|
||||
@@ -80,7 +82,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
break;
|
||||
}
|
||||
|
||||
$search = (($_GET['search']) ? $_GET['search'] : '');
|
||||
$search = $_GET['search'] ?? '';
|
||||
if($search) {
|
||||
if(strpos($search,'#') === 0) {
|
||||
$hashtags = substr($search,1);
|
||||
@@ -128,17 +130,19 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$pf = ((x($_GET,'pf')) ? $_GET['pf'] : '');
|
||||
$unseen = ((x($_GET,'unseen')) ? $_GET['unseen'] : '');
|
||||
|
||||
if (Apps::system_app_installed(local_channel(),'Affinity Tool')) {
|
||||
if (Apps::system_app_installed(local_channel(),'Affinity Tool')) {
|
||||
$affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1));
|
||||
if ($affinity_locked) {
|
||||
set_pconfig(local_channel(),'affinity','cmin',$cmin);
|
||||
set_pconfig(local_channel(),'affinity','cmax',$cmax);
|
||||
set_pconfig(local_channel(),'affinity','cmin',$cmin);
|
||||
set_pconfig(local_channel(),'affinity','cmax',$cmax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(x($_GET,'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen)
|
||||
$nouveau = true;
|
||||
|
||||
$cid_r = [];
|
||||
|
||||
if($cid) {
|
||||
$cid_r = q("SELECT abook.abook_xchan, xchan.xchan_addr, xchan.xchan_name, xchan.xchan_url, xchan.xchan_photo_s, xchan.xchan_pubforum from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and abook_blocked = 0 limit 1",
|
||||
intval($cid),
|
||||
@@ -453,6 +457,8 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
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']) . "' ) ";
|
||||
|
||||
$items = [];
|
||||
|
||||
if($nouveau && $load) {
|
||||
// "New Item View" - show all items unthreaded in reverse created date order
|
||||
$items = q("SELECT item.*, item.id AS item_id, created FROM item
|
||||
|
||||
@@ -11,7 +11,7 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
function init() {
|
||||
|
||||
$cmd = ((argc() > 1) ? argv(1) : '');
|
||||
|
||||
|
||||
if($cmd === 'autofill.json') {
|
||||
require_once('library/urlify/URLify.php');
|
||||
$result = array('error' => false, 'message' => '');
|
||||
@@ -20,14 +20,14 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
$x = false;
|
||||
|
||||
if(get_config('system','unicode_usernames')) {
|
||||
$x = punify(mb_strtolower($n));
|
||||
$x = punify(mb_strtolower($n));
|
||||
}
|
||||
|
||||
if((! $x) || strlen($x) > 64)
|
||||
$x = strtolower(\URLify::transliterate($n));
|
||||
|
||||
|
||||
$test = array();
|
||||
|
||||
|
||||
// first name
|
||||
if(strpos($x,' '))
|
||||
$test[] = legal_webbie(substr($x,0,strpos($x,' ')));
|
||||
@@ -44,19 +44,19 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
|
||||
json_return_and_die(check_webbie($test));
|
||||
}
|
||||
|
||||
|
||||
if($cmd === 'checkaddr.json') {
|
||||
require_once('library/urlify/URLify.php');
|
||||
$result = array('error' => false, 'message' => '');
|
||||
$n = trim($_REQUEST['nick']);
|
||||
if(! $n) {
|
||||
$n = trim($_REQUEST['name']);
|
||||
$n = trim($_REQUEST['name']);
|
||||
}
|
||||
|
||||
$x = false;
|
||||
|
||||
if(get_config('system','unicode_usernames')) {
|
||||
$x = punify(mb_strtolower($n));
|
||||
$x = punify(mb_strtolower($n));
|
||||
}
|
||||
|
||||
if((! $x) || strlen($x) > 64)
|
||||
@@ -64,7 +64,7 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
$test = array();
|
||||
|
||||
|
||||
// first name
|
||||
if(strpos($x,' '))
|
||||
$test[] = legal_webbie(substr($x,0,strpos($x,' ')));
|
||||
@@ -80,57 +80,57 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
$test[] = $n;
|
||||
$test[] = $n . mt_rand(1000,9999);
|
||||
}
|
||||
|
||||
|
||||
for($y = 0; $y < 100; $y ++)
|
||||
$test[] = 'id' . mt_rand(1000,9999);
|
||||
|
||||
|
||||
json_return_and_die(check_webbie($test));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
$arr = $_POST;
|
||||
|
||||
|
||||
$acc = \App::get_account();
|
||||
$arr['account_id'] = get_account_id();
|
||||
|
||||
// prevent execution by delegated channels as well as those not logged in.
|
||||
|
||||
// prevent execution by delegated channels as well as those not logged in.
|
||||
// get_account_id() returns the account_id from the session. But \App::$account
|
||||
// may point to the original authenticated account.
|
||||
|
||||
// may point to the original authenticated account.
|
||||
|
||||
if((! $acc) || ($acc['account_id'] != $arr['account_id'])) {
|
||||
notice( t('Permission denied.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$result = create_identity($arr);
|
||||
|
||||
|
||||
if(! $result['success']) {
|
||||
notice($result['message']);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$newuid = $result['channel']['channel_id'];
|
||||
|
||||
|
||||
change_channel($result['channel']['channel_id']);
|
||||
|
||||
$next_page = get_config('system', 'workflow_channel_next', 'profiles');
|
||||
|
||||
$next_page = get_config('system', 'workflow_channel_next', 'profiles');
|
||||
goaway(z_root() . '/' . $next_page);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
$acc = \App::get_account();
|
||||
|
||||
|
||||
if((! $acc) || $acc['account_id'] != get_account_id()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$default_role = '';
|
||||
$aid = get_account_id();
|
||||
if($aid) {
|
||||
@@ -140,7 +140,7 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
if($r && (! intval($r[0]['total']))) {
|
||||
$default_role = get_config('system','default_permissions_role','social');
|
||||
}
|
||||
|
||||
|
||||
$limit = account_service_class_fetch(get_account_id(),'total_identities');
|
||||
$canadd = true;
|
||||
if($r && ($limit !== false)) {
|
||||
@@ -155,7 +155,7 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$name_help = '<span id="name_help_loading" style="display:none">' . t('Loading') . '</span><span id="name_help_text">';
|
||||
$name_help .= (($default_role)
|
||||
$name_help .= (($default_role)
|
||||
? t('Your real name is recommended.')
|
||||
: t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"')
|
||||
);
|
||||
@@ -176,10 +176,10 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
$nickhub = '@' . \App::get_hostname();
|
||||
$nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), $nick_help, "*");
|
||||
$role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role compatible with your usage needs and privacy requirements.') . '<br>' . '<a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles);
|
||||
|
||||
|
||||
$o = replace_macros(get_markup_template('new_channel.tpl'), array(
|
||||
'$title' => t('Create a Channel'),
|
||||
'$desc' => t('A channel is a unique network identity. It can represent a person (social network profile), a forum (group), a business or celebrity page, a newsfeed, and many other things.') ,
|
||||
'$desc' => t('A channel is a unique network identity. It can represent a person (social network profile), a forum (group), a business or celebrity page, a newsfeed, and many other things.') ,
|
||||
'$label_import' => t('or <a href="import">import an existing channel</a> from another location.'),
|
||||
'$name' => $name,
|
||||
'$role' => $role,
|
||||
@@ -190,10 +190,10 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
'$channel_usage_message' => $channel_usage_message,
|
||||
'$canadd' => $canadd
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,15 +6,17 @@ require_once('include/bbcode.php');
|
||||
class Notifications extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
nav_set_selected('Notifications');
|
||||
|
||||
|
||||
$o = '';
|
||||
$notif_content = '';
|
||||
$notifications_available = false;
|
||||
|
||||
$r = q("select count(*) as total from notify where uid = %d and seen = 0",
|
||||
intval(local_channel())
|
||||
@@ -24,7 +26,8 @@ class Notifications extends \Zotlabs\Web\Controller {
|
||||
and seen = 0 order by created desc limit 50",
|
||||
intval(local_channel())
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$r1 = q("select * from notify where uid = %d
|
||||
and seen = 0 order by created desc limit 50",
|
||||
intval(local_channel())
|
||||
@@ -36,12 +39,12 @@ class Notifications extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
$r = array_merge($r1,$r2);
|
||||
}
|
||||
|
||||
|
||||
if($r) {
|
||||
$notifications_available = 1;
|
||||
$notifications_available = true;
|
||||
foreach ($r as $rr) {
|
||||
$x = strip_tags(bbcode($rr['msg']));
|
||||
$notif_content = replace_macros(get_markup_template('notify.tpl'),array(
|
||||
$notif_content .= replace_macros(get_markup_template('notify.tpl'),array(
|
||||
'$item_link' => z_root().'/notify/view/'. $rr['id'],
|
||||
'$item_image' => $rr['photo'],
|
||||
'$item_text' => $x,
|
||||
@@ -54,15 +57,15 @@ class Notifications extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
$notif_content = t('No more system notifications.');
|
||||
}
|
||||
|
||||
|
||||
$o .= replace_macros(get_markup_template('notifications.tpl'),array(
|
||||
'$notif_header' => t('System Notifications'),
|
||||
'$notif_link_mark_seen' => t('Mark all seen'),
|
||||
'$notif_content' => $notif_content,
|
||||
'$notifications_available' => $notifications_available,
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,24 +11,24 @@ require_once('include/security.php');
|
||||
class Oep extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
logger('oep: ' . print_r($_REQUEST,true), LOGGER_DEBUG, LOG_INFO);
|
||||
|
||||
|
||||
$html = ((argc() > 1 && argv(1) === 'html') ? true : false);
|
||||
if($_REQUEST['url']) {
|
||||
$_REQUEST['url'] = strip_zids($_REQUEST['url']);
|
||||
$url = $_REQUEST['url'];
|
||||
}
|
||||
|
||||
|
||||
if(! $url)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
|
||||
$maxwidth = $_REQUEST['maxwidth'];
|
||||
$maxheight = $_REQUEST['maxheight'];
|
||||
$format = $_REQUEST['format'];
|
||||
if($format && $format !== 'json')
|
||||
http_status_exit(501, 'Not implemented');
|
||||
|
||||
|
||||
if(fnmatch('*/photos/*/album/*',$url))
|
||||
$arr = $this->oep_album_reply($_REQUEST);
|
||||
elseif(fnmatch('*/photos/*/image/*',$url))
|
||||
@@ -47,7 +47,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
$arr = $this->oep_cards_reply($_REQUEST);
|
||||
elseif(fnmatch('*/articles/*',$url))
|
||||
$arr = $this->oep_articles_reply($_REQUEST);
|
||||
|
||||
|
||||
if($arr) {
|
||||
if($html) {
|
||||
if($arr['type'] === 'rich') {
|
||||
@@ -61,13 +61,13 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
http_status_exit(404,'Not found');
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function oep_display_reply($args) {
|
||||
|
||||
|
||||
$ret = array();
|
||||
$url = $args['url'];
|
||||
$maxwidth = intval($args['maxwidth']);
|
||||
@@ -83,8 +83,8 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
$p = q("select * from item where mid like '%s' limit 1",
|
||||
dbesc($res . '%')
|
||||
$p = q("select * from item where mid = '%s' limit 1",
|
||||
dbesc($res)
|
||||
);
|
||||
|
||||
if(! $p)
|
||||
@@ -92,7 +92,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
|
||||
$c = channelx_by_n($p[0]['uid']);
|
||||
|
||||
|
||||
|
||||
if(! ($c && $res))
|
||||
return;
|
||||
|
||||
@@ -100,27 +100,27 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
|
||||
$sql_extra = item_permissions_sql($c['channel_id']);
|
||||
|
||||
$p = q("select * from item where mid like '%s' and uid = %d $sql_extra $item_normal limit 1",
|
||||
dbesc($res . '%'),
|
||||
|
||||
$p = q("select * from item where mid = '%s' and uid = %d $sql_extra $item_normal limit 1",
|
||||
dbesc($res),
|
||||
intval($c['channel_id'])
|
||||
);
|
||||
|
||||
if(! $p)
|
||||
return;
|
||||
|
||||
|
||||
xchan_query($p,true);
|
||||
$p = fetch_post_tags($p,true);
|
||||
|
||||
// This function can get tripped up if the item is already a reshare
|
||||
// (the multiple share declarations do not parse cleanly if nested)
|
||||
// (the multiple share declarations do not parse cleanly if nested)
|
||||
// So build a template with a known nonsense string as the content, and then
|
||||
// replace that known string with the actual rendered content, sending
|
||||
// each content layer through bbcode() separately.
|
||||
|
||||
$x = '2eGriplW^*Jmf4';
|
||||
|
||||
|
||||
|
||||
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
|
||||
"' profile='".$p[0]['author']['xchan_url'] .
|
||||
"' avatar='".$p[0]['author']['xchan_photo_s'].
|
||||
@@ -131,29 +131,29 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
if($p[0]['title'])
|
||||
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
|
||||
|
||||
$o .= $x;
|
||||
$o .= $x;
|
||||
$o .= "[/share]";
|
||||
$o = bbcode($o);
|
||||
|
||||
|
||||
$o = str_replace($x,bbcode($p[0]['body']),$o);
|
||||
|
||||
|
||||
$ret['type'] = 'rich';
|
||||
|
||||
|
||||
$w = (($maxwidth) ? $maxwidth : 640);
|
||||
$h = (($maxheight) ? $maxheight : intval($w * 2 / 3));
|
||||
|
||||
|
||||
$ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>';
|
||||
|
||||
|
||||
$ret['width'] = $w;
|
||||
$ret['height'] = $h;
|
||||
|
||||
|
||||
return $ret;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function oep_cards_reply($args) {
|
||||
|
||||
|
||||
$ret = [];
|
||||
$url = $args['url'];
|
||||
$maxwidth = intval($args['maxwidth']);
|
||||
@@ -164,7 +164,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
$res = $matches[3];
|
||||
}
|
||||
if(! ($nick && $res))
|
||||
return $ret;
|
||||
return $ret;
|
||||
|
||||
$channel = channelx_by_nick($nick);
|
||||
|
||||
@@ -187,8 +187,8 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$r = q("select * from item
|
||||
where item.uid = %d and item_type = %d
|
||||
$r = q("select * from item
|
||||
where item.uid = %d and item_type = %d
|
||||
$sql_extra order by item.created desc",
|
||||
intval($channel['channel_id']),
|
||||
intval(ITEM_TYPE_CARD)
|
||||
@@ -208,7 +208,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
|
||||
$x = '2eGriplW^*Jmf4';
|
||||
|
||||
|
||||
|
||||
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
|
||||
"' profile='".$p[0]['author']['xchan_url'] .
|
||||
"' avatar='".$p[0]['author']['xchan_photo_s'].
|
||||
@@ -219,28 +219,28 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
if($p[0]['title'])
|
||||
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
|
||||
|
||||
$o .= $x;
|
||||
$o .= $x;
|
||||
$o .= "[/share]";
|
||||
$o = bbcode($o);
|
||||
|
||||
|
||||
$o = str_replace($x,bbcode($p[0]['body']),$o);
|
||||
|
||||
|
||||
$ret['type'] = 'rich';
|
||||
|
||||
|
||||
$w = (($maxwidth) ? $maxwidth : 640);
|
||||
$h = (($maxheight) ? $maxheight : intval($w * 2 / 3));
|
||||
|
||||
|
||||
$ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>';
|
||||
|
||||
|
||||
$ret['width'] = $w;
|
||||
$ret['height'] = $h;
|
||||
|
||||
|
||||
return $ret;
|
||||
|
||||
|
||||
}
|
||||
|
||||
function oep_articles_reply($args) {
|
||||
|
||||
|
||||
$ret = [];
|
||||
$url = $args['url'];
|
||||
$maxwidth = intval($args['maxwidth']);
|
||||
@@ -251,7 +251,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
$res = $matches[3];
|
||||
}
|
||||
if(! ($nick && $res))
|
||||
return $ret;
|
||||
return $ret;
|
||||
|
||||
$channel = channelx_by_nick($nick);
|
||||
|
||||
@@ -273,8 +273,8 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$r = q("select * from item
|
||||
where item.uid = %d and item_type = %d
|
||||
$r = q("select * from item
|
||||
where item.uid = %d and item_type = %d
|
||||
$sql_extra order by item.created desc",
|
||||
intval($channel['channel_id']),
|
||||
intval(ITEM_TYPE_ARTICLE)
|
||||
@@ -294,7 +294,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
|
||||
$x = '2eGriplW^*Jmf4';
|
||||
|
||||
|
||||
|
||||
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
|
||||
"' profile='".$p[0]['author']['xchan_url'] .
|
||||
"' avatar='".$p[0]['author']['xchan_photo_s'].
|
||||
@@ -305,71 +305,71 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
if($p[0]['title'])
|
||||
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
|
||||
|
||||
$o .= $x;
|
||||
$o .= $x;
|
||||
$o .= "[/share]";
|
||||
$o = bbcode($o);
|
||||
|
||||
|
||||
$o = str_replace($x,bbcode($p[0]['body']),$o);
|
||||
|
||||
|
||||
$ret['type'] = 'rich';
|
||||
|
||||
|
||||
$w = (($maxwidth) ? $maxwidth : 640);
|
||||
$h = (($maxheight) ? $maxheight : intval($w * 2 / 3));
|
||||
|
||||
|
||||
$ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>';
|
||||
|
||||
|
||||
$ret['width'] = $w;
|
||||
$ret['height'] = $h;
|
||||
|
||||
|
||||
return $ret;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function oep_mid_reply($args) {
|
||||
|
||||
|
||||
$ret = array();
|
||||
$url = $args['url'];
|
||||
$maxwidth = intval($args['maxwidth']);
|
||||
$maxheight = intval($args['maxheight']);
|
||||
|
||||
|
||||
if(preg_match('#//(.*?)/(.*?)/(.*?)/(.*?)mid\=(.*?)(&|$)#',$url,$matches)) {
|
||||
$chn = $matches[3];
|
||||
$res = $matches[5];
|
||||
}
|
||||
|
||||
|
||||
if(! ($chn && $res))
|
||||
return;
|
||||
$c = q("select * from channel where channel_address = '%s' limit 1",
|
||||
dbesc($chn)
|
||||
);
|
||||
|
||||
|
||||
if(! $c)
|
||||
return;
|
||||
|
||||
if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_stream'))
|
||||
return;
|
||||
|
||||
|
||||
$sql_extra = item_permissions_sql($c[0]['channel_id']);
|
||||
|
||||
|
||||
$p = q("select * from item where mid = '%s' and uid = %d $sql_extra limit 1",
|
||||
dbesc($res),
|
||||
intval($c[0]['channel_id'])
|
||||
);
|
||||
if(! $p)
|
||||
return;
|
||||
|
||||
|
||||
xchan_query($p,true);
|
||||
$p = fetch_post_tags($p,true);
|
||||
|
||||
// This function can get tripped up if the item is already a reshare
|
||||
// (the multiple share declarations do not parse cleanly if nested)
|
||||
// (the multiple share declarations do not parse cleanly if nested)
|
||||
// So build a template with a known nonsense string as the content, and then
|
||||
// replace that known string with the actual rendered content, sending
|
||||
// each content layer through bbcode() separately.
|
||||
|
||||
$x = '2eGriplW^*Jmf4';
|
||||
|
||||
|
||||
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
|
||||
"' profile='".$p[0]['author']['xchan_url'] .
|
||||
"' avatar='".$p[0]['author']['xchan_photo_s'].
|
||||
@@ -379,52 +379,52 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
"' message_id='".$p[0]['mid']."']";
|
||||
if($p[0]['title'])
|
||||
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
|
||||
$o .= $x;
|
||||
$o .= $x;
|
||||
$o .= "[/share]";
|
||||
$o = bbcode($o);
|
||||
|
||||
|
||||
$o = str_replace($x,bbcode($p[0]['body']),$o);
|
||||
|
||||
$ret['type'] = 'rich';
|
||||
|
||||
|
||||
$w = (($maxwidth) ? $maxwidth : 640);
|
||||
$h = (($maxheight) ? $maxheight : intval($w * 2 / 3));
|
||||
|
||||
|
||||
$ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>';
|
||||
|
||||
|
||||
$ret['width'] = $w;
|
||||
$ret['height'] = $h;
|
||||
|
||||
|
||||
return $ret;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function oep_profile_reply($args) {
|
||||
|
||||
|
||||
|
||||
|
||||
require_once('include/channel.php');
|
||||
|
||||
$url = $args['url'];
|
||||
|
||||
|
||||
if(preg_match('#//(.*?)/(.*?)/(.*?)(/|\?|&|$)#',$url,$matches)) {
|
||||
$chn = $matches[3];
|
||||
}
|
||||
|
||||
|
||||
if(! $chn)
|
||||
return;
|
||||
|
||||
|
||||
$c = channelx_by_nick($chn);
|
||||
|
||||
|
||||
if(! $c)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
$maxwidth = intval($args['maxwidth']);
|
||||
$maxheight = intval($args['maxheight']);
|
||||
|
||||
|
||||
$width = 800;
|
||||
$height = 375;
|
||||
|
||||
|
||||
if($maxwidth) {
|
||||
$width = $maxwidth;
|
||||
$height = (375 / 800) * $width;
|
||||
@@ -434,59 +434,59 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
$width = (800 / 375) * $maxheight;
|
||||
$height = $maxheight;
|
||||
}
|
||||
}
|
||||
}
|
||||
$ret = array();
|
||||
|
||||
|
||||
$ret['type'] = 'rich';
|
||||
$ret['width'] = intval($width);
|
||||
$ret['height'] = intval($height);
|
||||
|
||||
|
||||
$ret['html'] = get_zcard_embed($c,get_observer_hash(),array('width' => $width, 'height' => $height));
|
||||
|
||||
|
||||
return $ret;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function oep_album_reply($args) {
|
||||
|
||||
|
||||
$ret = array();
|
||||
$url = $args['url'];
|
||||
$maxwidth = intval($args['maxwidth']);
|
||||
$maxheight = intval($args['maxheight']);
|
||||
|
||||
|
||||
if(preg_match('|//(.*?)/(.*?)/(.*?)/album/|',$url,$matches)) {
|
||||
$chn = $matches[3];
|
||||
$res = basename($url);
|
||||
}
|
||||
|
||||
|
||||
if(! ($chn && $res))
|
||||
return;
|
||||
$c = q("select * from channel where channel_address = '%s' limit 1",
|
||||
dbesc($chn)
|
||||
);
|
||||
|
||||
|
||||
if(! $c)
|
||||
return;
|
||||
|
||||
|
||||
if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_files'))
|
||||
return;
|
||||
|
||||
$sql_extra = permissions_sql($c[0]['channel_id']);
|
||||
|
||||
|
||||
$p = q("select resource_id from photo where album = '%s' and uid = %d and imgscale = 0 $sql_extra order by created desc limit 1",
|
||||
dbesc($res),
|
||||
intval($c[0]['channel_id'])
|
||||
);
|
||||
if(! $p)
|
||||
return;
|
||||
|
||||
|
||||
$res = $p[0]['resource_id'];
|
||||
|
||||
|
||||
$r = q("select height, width, imgscale, resource_id from photo where uid = %d and resource_id = '%s' $sql_extra order by imgscale asc",
|
||||
intval($c[0]['channel_id']),
|
||||
dbesc($res)
|
||||
);
|
||||
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$foundres = false;
|
||||
@@ -494,62 +494,62 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
continue;
|
||||
if($maxwidth && $rr['width'] > $maxwidth)
|
||||
continue;
|
||||
$foundres = true;
|
||||
$foundres = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if($foundres) {
|
||||
$ret['type'] = 'link';
|
||||
$ret['thumbnail_url'] = z_root() . '/photo/' . '/' . $rr['resource_id'] . '-' . $rr['imgscale'];
|
||||
$ret['thumbnail_width'] = $rr['width'];
|
||||
$ret['thumbnail_height'] = $rr['height'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
return $ret;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function oep_phototop_reply($args) {
|
||||
|
||||
|
||||
$ret = array();
|
||||
$url = $args['url'];
|
||||
$maxwidth = intval($args['maxwidth']);
|
||||
$maxheight = intval($args['maxheight']);
|
||||
|
||||
|
||||
if(preg_match('|//(.*?)/(.*?)/(.*?)$|',$url,$matches)) {
|
||||
$chn = $matches[3];
|
||||
}
|
||||
|
||||
|
||||
if(! $chn)
|
||||
return;
|
||||
$c = q("select * from channel where channel_address = '%s' limit 1",
|
||||
dbesc($chn)
|
||||
);
|
||||
|
||||
|
||||
if(! $c)
|
||||
return;
|
||||
|
||||
|
||||
if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_files'))
|
||||
return;
|
||||
|
||||
$sql_extra = permissions_sql($c[0]['channel_id']);
|
||||
|
||||
|
||||
$p = q("select resource_id from photo where uid = %d and imgscale = 0 $sql_extra order by created desc limit 1",
|
||||
intval($c[0]['channel_id'])
|
||||
);
|
||||
if(! $p)
|
||||
return;
|
||||
|
||||
|
||||
$res = $p[0]['resource_id'];
|
||||
|
||||
|
||||
$r = q("select height, width, imgscale, resource_id from photo where uid = %d and resource_id = '%s' $sql_extra order by imgscale asc",
|
||||
intval($c[0]['channel_id']),
|
||||
dbesc($res)
|
||||
);
|
||||
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$foundres = false;
|
||||
@@ -557,42 +557,42 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
continue;
|
||||
if($maxwidth && $rr['width'] > $maxwidth)
|
||||
continue;
|
||||
$foundres = true;
|
||||
$foundres = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if($foundres) {
|
||||
$ret['type'] = 'link';
|
||||
$ret['thumbnail_url'] = z_root() . '/photo/' . '/' . $rr['resource_id'] . '-' . $rr['imgscale'];
|
||||
$ret['thumbnail_width'] = $rr['width'];
|
||||
$ret['thumbnail_height'] = $rr['height'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
return $ret;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function oep_photo_reply($args) {
|
||||
|
||||
|
||||
$ret = array();
|
||||
$url = $args['url'];
|
||||
$maxwidth = intval($args['maxwidth']);
|
||||
$maxheight = intval($args['maxheight']);
|
||||
|
||||
|
||||
if(preg_match('|//(.*?)/(.*?)/(.*?)/image/|',$url,$matches)) {
|
||||
$chn = $matches[3];
|
||||
$res = basename($url);
|
||||
}
|
||||
|
||||
|
||||
if(! ($chn && $res))
|
||||
return;
|
||||
$c = q("select * from channel where channel_address = '%s' limit 1",
|
||||
dbesc($chn)
|
||||
);
|
||||
|
||||
|
||||
if(! $c)
|
||||
return;
|
||||
|
||||
@@ -600,13 +600,13 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
|
||||
$sql_extra = permissions_sql($c[0]['channel_id']);
|
||||
|
||||
|
||||
|
||||
|
||||
$r = q("select height, width, imgscale, resource_id from photo where uid = %d and resource_id = '%s' $sql_extra order by imgscale asc",
|
||||
intval($c[0]['channel_id']),
|
||||
dbesc($res)
|
||||
);
|
||||
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$foundres = false;
|
||||
@@ -614,20 +614,20 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
continue;
|
||||
if($maxwidth && $rr['width'] > $maxwidth)
|
||||
continue;
|
||||
$foundres = true;
|
||||
$foundres = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if($foundres) {
|
||||
$ret['type'] = 'link';
|
||||
$ret['thumbnail_url'] = z_root() . '/photo/' . '/' . $rr['resource_id'] . '-' . $rr['imgscale'];
|
||||
$ret['thumbnail_width'] = $rr['width'];
|
||||
$ret['thumbnail_height'] = $rr['height'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
return $ret;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
$channel = channelx_by_n($r[0]['uid']);
|
||||
|
||||
// Now we'll see if we can access the photo
|
||||
$e = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d $sql_extra LIMIT 1",
|
||||
$e = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
|
||||
dbesc($photo),
|
||||
intval($resolution)
|
||||
);
|
||||
|
||||
447
Zotlabs/Module/Regate.php
Normal file
447
Zotlabs/Module/Regate.php
Normal file
@@ -0,0 +1,447 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/security.php');
|
||||
|
||||
/**
|
||||
*
|
||||
* @version 2.0.0
|
||||
* @author hilmar runge
|
||||
* @since 2020-03-03
|
||||
* Check verification pin
|
||||
* input field email address
|
||||
* input field pin (told during register)
|
||||
* check duty
|
||||
* check startup and expire
|
||||
* compare email address
|
||||
* check pin
|
||||
* limited tries to enter the correct pin/pass 2 handle via f2b
|
||||
* on success create account and update register
|
||||
*
|
||||
*/
|
||||
|
||||
define ( 'REGISTER_AGREED', 0x0020 );
|
||||
define ( 'REGISTER_DENIED', 0x0040 );
|
||||
|
||||
class Regate extends \Zotlabs\Web\Controller {
|
||||
|
||||
const MYP = 'ZAR'; //ZAR1x
|
||||
const VERSION = '2.0.0';
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
check_form_security_token_redirectOnErr('/', 'regate');
|
||||
|
||||
if ( argc() > 1 ) {
|
||||
$did2 = hex2bin( substr( argv(1), 0, -1) );
|
||||
$didx = substr( argv(1), -1 );
|
||||
}
|
||||
|
||||
$msg = '';
|
||||
$nextpage = '';
|
||||
|
||||
if ($did2) {
|
||||
|
||||
$nowhhmm = date('Hi');
|
||||
$day = date('N');
|
||||
$now = datetime_convert();
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
$isduty = zar_register_dutystate();
|
||||
|
||||
if (!$_SESSION['zar']['invite_in_progress'] && ($isduty['isduty'] !== false && $isduty['isduty'] != 1)) {
|
||||
// normally, that should never happen here
|
||||
// log suitable for fail2ban also
|
||||
$logmsg = 'ZAR1230S Unexpected registration verification request for '
|
||||
. get_config('system','sitename') . ' arrived from § ' . $ip . ' §';
|
||||
zar_log($logmsg);
|
||||
goaway(z_root());
|
||||
}
|
||||
|
||||
// do we have a valid dId2 ?
|
||||
if (($didx == 'a' && substr( $did2 , -2) == substr( base_convert( md5( substr( $did2, 1, -2) ),16 ,10), -2)) || ($didx == 'e') || ($didx == 'i')) {
|
||||
// check startup and expiration via [=[register
|
||||
$r = q("SELECT * FROM register WHERE reg_vital = 1 AND reg_did2 = '%s' ORDER BY reg_created DESC ",
|
||||
dbesc($did2)
|
||||
);
|
||||
if ($r && count($r)) {
|
||||
$r = $r[0];
|
||||
// check timeframe
|
||||
if ($r['reg_startup'] <= $now && $r['reg_expires'] >= $now) {
|
||||
if (isset($_POST['resend']) && $didx == 'e') {
|
||||
$re = q("SELECT * FROM register WHERE reg_vital = 1 AND reg_didx = 'e' AND reg_did2 = '%s' ORDER BY reg_created DESC ", dbesc($r['reg_did2']) );
|
||||
if ($re) {
|
||||
$re = $re[0];
|
||||
$reonar = json_decode($re['reg_stuff'], true);
|
||||
if ($reonar) {
|
||||
$reonar['subject'] = 'Re,Fwd,' . $reonar['subject'];
|
||||
$zm = zar_reg_mail($reonar);
|
||||
$msg = (($zm) ? t('Email resent') : t('Email resend failed'));
|
||||
zar_log((($zm) ? 'ZAR1238I' : 'ZAR1238E') . ' ' . $msg . ' ' . $r['reg_did2']);
|
||||
info($msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check hash
|
||||
if ( $didx == 'a' )
|
||||
$acpin = (preg_match('/^[0-9]{6,6}$/', $_POST['acpin']) ? $_POST['acpin'] : false);
|
||||
elseif ( $didx == 'e' )
|
||||
$acpin = (preg_match('/^[0-9a-f]{24,24}$/', $_POST['acpin']) ? $_POST['acpin'] : false);
|
||||
elseif ( $didx == 'i' )
|
||||
$acpin = $r['reg_hash'];
|
||||
else
|
||||
$acpin = false;
|
||||
|
||||
if ( $acpin && ($r['reg_hash'] == $acpin )) {
|
||||
|
||||
$flags = $r['reg_flags'];
|
||||
if (($flags & ACCOUNT_UNVERIFIED) == ACCOUNT_UNVERIFIED) {
|
||||
|
||||
// verification success
|
||||
$msg_code = 'ZAR1237I';
|
||||
$msg = t('Verification successful');
|
||||
$reonar = json_decode( $r['reg_stuff'], true);
|
||||
$reonar['valid'] = $now . ',' . $ip . ' ' . $did2 . ' ' . $msg_code . ' ' . $msg;
|
||||
|
||||
// clear flag
|
||||
$flags &= $flags ^ ACCOUNT_UNVERIFIED;
|
||||
|
||||
// are we invited by the admin?
|
||||
$isa = get_account_by_id($r['reg_uid']);
|
||||
$isa = ($isa && ($isa['account_roles'] && ACCOUNT_ROLE_ADMIN));
|
||||
|
||||
// approve contra invite by admin
|
||||
if ($isa && get_config('system','register_policy') == REGISTER_APPROVE) {
|
||||
$flags &= $flags ^ ACCOUNT_PENDING;
|
||||
}
|
||||
|
||||
// sth todo?
|
||||
$vital = $flags == 0 ? 0 : 1;
|
||||
|
||||
// set flag
|
||||
$flags |= REGISTER_AGREED;
|
||||
zar_log($msg . ' ' . $did2 . ':flags' . $flags . ',rid' . $r['reg_id']);
|
||||
|
||||
q("START TRANSACTION");
|
||||
|
||||
$qu = q("UPDATE register SET reg_stuff = '%s', reg_vital = %d, reg_flags = %d "
|
||||
." WHERE reg_id = %d ",
|
||||
dbesc(json_encode($reonar)),
|
||||
intval($vital),
|
||||
intval($flags),
|
||||
intval($r['reg_id'])
|
||||
);
|
||||
|
||||
if (($flags & ACCOUNT_PENDING ) == ACCOUNT_PENDING) {
|
||||
$nextpage = 'regate/' . bin2hex($did2) . $didx;
|
||||
q("COMMIT");
|
||||
}
|
||||
elseif (($flags ^ REGISTER_AGREED) == 0) {
|
||||
|
||||
$cra = create_account_from_register([ 'reg_id' => $r['reg_id'] ]);
|
||||
|
||||
if ($cra['success']) {
|
||||
|
||||
q("COMMIT");
|
||||
$msg = t('Account successfull created');
|
||||
// zar_log($msg . ':' . print_r($cra, true));
|
||||
zar_log('ZAR1238I ' . $msg . ' ' . $cra['account']['account_email']
|
||||
. ' ' . $cra['account']['account_language']);
|
||||
|
||||
authenticate_success($cra['account'],null,true,false,true);
|
||||
|
||||
$nextpage = 'new_channel';
|
||||
|
||||
$auto_create = get_config('system', 'auto_channel_create', 1);
|
||||
|
||||
if($auto_create) {
|
||||
|
||||
$new_channel = ['success' => false];
|
||||
|
||||
// We do not reserve a channel_address before the registration is verified
|
||||
// and possibly approved by the admin.
|
||||
// If the provided channel_address has been claimed meanwhile,
|
||||
// we will proceed to /new_channel.
|
||||
|
||||
if(isset($reonar['chan.did1']) && check_webbie([$reonar['chan.did1']])) {
|
||||
|
||||
// prepare channel creation
|
||||
if($reonar['chan.name'])
|
||||
set_aconfig($cra['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']);
|
||||
|
||||
if($reonar['chan.did1'])
|
||||
set_aconfig($cra['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']);
|
||||
|
||||
$permissions_role = get_config('system','default_permissions_role');
|
||||
if($permissions_role)
|
||||
set_aconfig($cra['account']['account_id'], 'register', 'permissions_role', $permissions_role);
|
||||
|
||||
// create channel
|
||||
$new_channel = auto_channel_create($cra['account']['account_id']);
|
||||
|
||||
if($new_channel['success']) {
|
||||
$channel_id = $new_channel['channel']['channel_id'];
|
||||
change_channel($channel_id);
|
||||
$nextpage = 'profiles/' . $channel_id;
|
||||
$msg_code = 'ZAR1239I';
|
||||
$msg = t('Channel successfull created') . ' ' . $did2;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$new_channel['success']) {
|
||||
$msg_code = 'ZAR1239E';
|
||||
$msg = t('Automatic channel creation failed. Please create a channel.') . ' ' . $did2;
|
||||
$nextpage = 'new_channel?name=' . $reonar['chan.name'];
|
||||
}
|
||||
|
||||
zar_log($msg_code . ' ' . $msg . ' ' . $reonar['chan.did1'] . ' (' . $reonar['chan.name'] . ')');
|
||||
|
||||
}
|
||||
unset($_SESSION['login_return_url']);
|
||||
}
|
||||
else {
|
||||
q("ROLLBACK");
|
||||
$msg_code = 'ZAR1238E';
|
||||
$msg = t('Account creation error');
|
||||
zar_log($msg_code . ' ' . $msg . ': ' . print_r($cra, true));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// new flags implemented and not recognized or sth like
|
||||
zar_log('ZAR1237D unexpected,' . $flags);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// nothing to confirm
|
||||
$msg_code = 'ZAR1236E';
|
||||
$msg = t('Verify failed');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg_code = 'ZAR1235E';
|
||||
$msg = t('Token verification failed');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg_code = 'ZAR1234W';
|
||||
$msg = t('Request not inside time frame');
|
||||
//info($r[0]['reg_startup'] . EOL . $r[0]['reg_expire'] );
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg_code = 'ZAR1232E';
|
||||
$msg = t('Identity unknown');
|
||||
zar_log($msg_code . ' ' . $msg . ':' . $did2 . $didx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg_code = 'ZAR1231E';
|
||||
$msg = t('dId2 mistaken');
|
||||
zar_log($msg_code . ' ' . $msg);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($msg > '') info($msg);
|
||||
goaway( z_root() . '/' . $nextpage );
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if (argc() == 1) {
|
||||
if(isset($_GET['reg_id'])) {
|
||||
if ( preg_match('/^.{2,64}\@[a-z0-9.-]{4,32}\.[a-z]{2,12}$/', $_GET['reg_id'] ) ) {
|
||||
// dId2 E email
|
||||
goaway(z_root() . '/regate/' . bin2hex($_GET['reg_id']) . 'e' );
|
||||
}
|
||||
if ( preg_match('/^d{1,1}[0-9]{5,10}$/', $_GET['reg_id'] ) ) {
|
||||
// dId2 A artifical & anonymous
|
||||
goaway(z_root() . '/regate/' . bin2hex($_GET['reg_id']) . 'a' );
|
||||
}
|
||||
notice(t('Identity unknown') . EOL);
|
||||
}
|
||||
|
||||
$o = replace_macros(get_markup_template('plain.tpl'), [
|
||||
'$title' => t('Your Registration ID'),
|
||||
'$now' => '<form action="regate" method="get"><input type="text" name="reg_id" class="form-control form-group"><button class="btn btn-primary float-right">Submit</button></form>'
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
$isduty = zar_register_dutystate();
|
||||
$nowfmt = $isduty['nowfmt'];
|
||||
$atform = $isduty['atform'];
|
||||
|
||||
if ($_SESSION['zar']['delayed']) {
|
||||
$o = replace_macros(get_markup_template('regate_pre.tpl'), [
|
||||
'$title' => t('Registration verification'),
|
||||
'$now' => $nowfmt,
|
||||
'$id' => $_SESSION['zar']['id'],
|
||||
'$pin' => $_SESSION['zar']['pin'],
|
||||
'$regdelay' => $_SESSION['zar']['regdelay'],
|
||||
'$regexpire' => $_SESSION['zar']['regexpire'],
|
||||
'$strings' => [
|
||||
t('Hold on, you can start verification in'),
|
||||
t('Please remember your verification token for ID'),
|
||||
'',
|
||||
t('Token validity')
|
||||
]
|
||||
]);
|
||||
unset($_SESSION['zar']['delayed']);
|
||||
return $o;
|
||||
}
|
||||
|
||||
if (argc() < 2)
|
||||
return;
|
||||
|
||||
$did2 = hex2bin( substr( argv(1), 0, -1) );
|
||||
$didx = substr( argv(1), -1 );
|
||||
$deny = argc() > 2 ? argv(2) : '';
|
||||
$deny = preg_match('/^[0-9a-f]{8,8}$/', $deny) ? hex2bin($deny) : false;
|
||||
$now = datetime_convert();
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
$pin = '';
|
||||
|
||||
if(isset($_SESSION['zar']['pin'])) {
|
||||
$pin = $_SESSION['zar']['pin'];
|
||||
unset($_SESSION['zar']['pin']);
|
||||
}
|
||||
|
||||
// do we have a valid dId2 ?
|
||||
if (($didx == 'a' && substr( $did2 , -2) == substr( base_convert( md5( substr( $did2, 1, -2) ),16 ,10), -2)) || ($didx == 'e') || ($didx == 'i')) {
|
||||
|
||||
$r = q("SELECT * FROM register WHERE reg_vital = 1 AND reg_didx = '%s' AND reg_did2 = '%s' ORDER BY reg_created DESC",
|
||||
dbesc($didx),
|
||||
dbesc($did2)
|
||||
);
|
||||
|
||||
if ($r && count($r) && $r[0]['reg_flags'] &= (ACCOUNT_UNVERIFIED | ACCOUNT_PENDING)) {
|
||||
$r = $r[0];
|
||||
|
||||
// provide a button in case
|
||||
$resend = (($r['reg_didx'] == 'e') ? t('Resend email') : '');
|
||||
|
||||
// is still only instance admins intervention required?
|
||||
if ($r['reg_flags'] == ACCOUNT_PENDING) {
|
||||
$o = replace_macros(get_markup_template('regate_post.tpl'), [
|
||||
'$title' => t('Registration status'),
|
||||
'$id' => $did2,
|
||||
'$strings' => [
|
||||
t('Verification successful!'),
|
||||
t('Your login ID is'),
|
||||
t('After your account has been approved by our administrator you will be able to login with your login ID and your provided password.')
|
||||
]
|
||||
]);
|
||||
}
|
||||
else {
|
||||
|
||||
if ($deny) {
|
||||
|
||||
if (substr($r['reg_hash'],0,4) == $deny) {
|
||||
zar_log('ZAR1134S email verfication denied ' . $did2);
|
||||
|
||||
$o = replace_macros(get_markup_template('plain.tpl'), [
|
||||
'$title' => t('Registration request revoked'),
|
||||
'$infos' => t('Sorry for any inconvience. Thank you for your response.')
|
||||
]);
|
||||
|
||||
$reonar = json_decode( $r['reg_stuff'], true);
|
||||
$reonar['deny'] = $now . ',' . $ip . ' ' . $did2 . ' ' . $msg;
|
||||
$flags = ( $r['reg_flags'] &= ( $r['reg_flags'] ^ ACCOUNT_UNVERIFIED) )
|
||||
| ( $r['reg_flags'] |= REGISTER_DENIED);
|
||||
$rd = q("UPDATE register SET reg_stuff='%s', reg_vital=0, reg_flags=%d WHERE reg_id = %d ",
|
||||
dbesc(json_encode($reonar)),
|
||||
intval($flags),
|
||||
intval($r['reg_id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
zar_log('ZAR1135E not awaited url parameter received');
|
||||
goaway(z_root);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if ( $r['reg_startup'] <= $now && $r['reg_expires'] >= $now) {
|
||||
$o = replace_macros(get_markup_template('regate.tpl'), [
|
||||
'$form_security_token' => get_form_security_token("regate"),
|
||||
'$title' => t('Registration verification'),
|
||||
'$desc' => t('Please enter your verification token for ID'),
|
||||
'$email_extra' => (($didx === 'e') ? t('Please check your email!') : ''),
|
||||
'$id' => $did2,
|
||||
// we might consider to not provide $pin if a registration delay is configured
|
||||
// and the pin turns out to be readable by bots
|
||||
'$pin' => $pin,
|
||||
'$did2' => bin2hex($did2) . $didx,
|
||||
'$now' => $nowfmt,
|
||||
'$atform' => $atform,
|
||||
'$resend' => $resend,
|
||||
'$submit' => t('Submit'),
|
||||
'$acpin' => [ 'acpin', t('Verification token'),'','' ]
|
||||
]);
|
||||
}
|
||||
else {
|
||||
// expired ?
|
||||
if ( $now > $r['reg_expires'] ) {
|
||||
$rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d ",
|
||||
intval($r['reg_id'])
|
||||
);
|
||||
|
||||
$o = replace_macros(get_markup_template('plain.tpl'), [
|
||||
'$infos' => t('ID expired'),
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
$email_extra = (($didx === 'e') ? t('Please check your email!') : '');
|
||||
|
||||
$o = replace_macros(get_markup_template('regate_pre.tpl'), [
|
||||
'$title' => t('Registration verification'),
|
||||
'$now' => $nowfmt,
|
||||
'$id' => $did2,
|
||||
'$countdown' => datetime_convert('UTC', 'UTC', $r['reg_startup'], 'c'),
|
||||
'$strings' => [
|
||||
t('Hold on, you can start verification in'),
|
||||
t('You will require the verification token for ID'),
|
||||
$email_extra
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg = t('Unknown or expired ID');
|
||||
zar_log('ZAR1132E ' . $msg . ':' . $did2 . ',' . $didx);
|
||||
$o = replace_macros(get_markup_template('plain.tpl'), [
|
||||
'$title' => $title,
|
||||
'$now' => $nowfmt,
|
||||
'$infos' => $msg
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
$msg = 'ZAR1131E ' . t('dId2 malformed');
|
||||
// $log = ' from § ' . $ip . ' §' . ' (' . dbesc($did2) . ')';
|
||||
zar_log($msg);
|
||||
$o = replace_macros(get_markup_template('plain.tpl'), [
|
||||
'$title' => $title,
|
||||
'$now' => $nowfmt,
|
||||
'$infos' => $msg
|
||||
]);
|
||||
}
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/channel.php');
|
||||
|
||||
|
||||
class Register extends Controller {
|
||||
|
||||
const MYP = 'ZAR'; // ZAR0x
|
||||
const VERSION = '2.0.0';
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
// ZAR0
|
||||
|
||||
$result = null;
|
||||
$cmd = ((argc() > 1) ? argv(1) : '');
|
||||
|
||||
|
||||
// Provide a stored request for somebody desiring a connection
|
||||
// when they first need to register someplace. Once they've
|
||||
// created a channel, we'll try to revive the connection request
|
||||
// created a channel, we'll try to revive the connection request
|
||||
// and process it.
|
||||
|
||||
|
||||
if($_REQUEST['connect'])
|
||||
$_SESSION['connect'] = $_REQUEST['connect'];
|
||||
|
||||
|
||||
switch($cmd) {
|
||||
case 'invite_check.json':
|
||||
$result = check_account_invite($_REQUEST['invite_code']);
|
||||
@@ -30,50 +39,161 @@ class Register extends Controller {
|
||||
case 'password_check.json':
|
||||
$result = check_account_password($_REQUEST['password1']);
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if($result) {
|
||||
json_return_and_die($result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
check_form_security_token_redirectOnErr('/register', 'register');
|
||||
|
||||
$max_dailies = intval(get_config('system','max_daily_registrations'));
|
||||
if($max_dailies) {
|
||||
$r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('1 day')
|
||||
);
|
||||
if($r && $r[0]['total'] >= $max_dailies) {
|
||||
notice( t('Maximum daily site registrations exceeded. Please try again tomorrow.') . EOL);
|
||||
/**
|
||||
* [hilmar:]
|
||||
* It may happen, the posted form arrives in a strange fashion. With the control of the duty hours
|
||||
* for registration, the input form was disabled at html. While receiving posted data, checks are
|
||||
* required if all is on the right road (most posts are not accepted during off duty).
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
$act = q("SELECT COUNT(*) AS act FROM account")[0]['act'];
|
||||
$is247 = false;
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
$sameip = intval(get_config('system','register_sameip', 3));
|
||||
$arr = $_POST;
|
||||
$invite_code = ((x($arr,'invite_code')) ? notags(trim($arr['invite_code'])) : '');
|
||||
$name = '';
|
||||
$nick = '';
|
||||
$email = ((x($arr,'email')) ? notags(punify(trim($arr['email']))) : '');
|
||||
$password = ((x($arr,'password')) ? trim($arr['password']) : '');
|
||||
$password2 = ((x($arr,'password2')) ? trim($arr['password2']) : '');
|
||||
$register_msg = ((x($arr,'register_msg')) ? notags(trim($arr['register_msg'])) : '');
|
||||
$reonar = [];
|
||||
$auto_create = get_config('system','auto_channel_create', 1);
|
||||
$duty = zar_register_dutystate();
|
||||
|
||||
if (!get_config('system', 'register_duty_jso')) {
|
||||
// if not yet configured default to true
|
||||
$duty = array( 'isduty' => true, 'atfrm' => '', 'nowfmt' => '');
|
||||
}
|
||||
|
||||
if($auto_create) {
|
||||
$name = escape_tags(trim($arr['name']));
|
||||
|
||||
$name_error = validate_channelname($name);
|
||||
if($name_error) {
|
||||
notice($name_error . EOL);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$nick = mb_strtolower(escape_tags(trim($arr['nickname'])));
|
||||
if(!$nick) {
|
||||
notice(t('Nickname is required.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if($nick === 'sys') {
|
||||
notice(t('Reserved nickname. Please choose another.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(check_webbie([$nick]) !== $nick) {
|
||||
notice(t('Nickname has unsupported characters or is already being used on this site.') . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(! x($_POST,'tos')) {
|
||||
notice( t('Please indicate acceptance of the Terms of Service. Registration failed.') . EOL);
|
||||
|
||||
$email_verify = get_config('system', 'verify_email');
|
||||
if ($email_verify && !$email) {
|
||||
notice(t('Email address required') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$policy = get_config('system','register_policy');
|
||||
|
||||
$email_verify = get_config('system','verify_email');
|
||||
|
||||
|
||||
|
||||
if ($email) {
|
||||
$email_result = check_account_email($email);
|
||||
if ($email_result['error']) {
|
||||
if ($email_result['email_unverified']) {
|
||||
goaway(z_root() . '/regate/' . bin2hex($email) . 'e');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// case when an invited prepares the own account by supply own pw, accept tos, prepage channel (if auto)
|
||||
if ($email && $invite_code) {
|
||||
if ( preg_match('/^[a-z0-9]{12,12}$/', $invite_code ) ) {
|
||||
$is247 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($act > 0 && !$is247 && !$duty['isduty']) {
|
||||
// normally (except very 1st timr after install), that should never arrive here (ie js hack or sth like)
|
||||
// log suitable for f2b also
|
||||
$logmsg = 'Unexpected registration request off duty';
|
||||
notice($logmsg);
|
||||
zar_log('ZAR0230S ' . $logmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($sameip) {
|
||||
$f = q("SELECT COUNT(reg_atip) AS atip FROM register WHERE reg_vital = 1 AND reg_atip = '%s' ",
|
||||
dbesc($ip)
|
||||
);
|
||||
if ($f && $f[0]['atip'] >= $sameip) {
|
||||
$logmsg = 'ZAR0239S Exceeding same ip register request of ' . $sameip;
|
||||
notice('Registrations from same IP exceeded.');
|
||||
zar_log($logmsg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$password) {
|
||||
notice(t('No password provided') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($password !== $password2) {
|
||||
notice(t('Passwords do not match') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$password_result = check_account_password($password);
|
||||
if(!empty($password_result['error'])) {
|
||||
$msg = $password_result['message'];
|
||||
notice($msg);
|
||||
zar_log($msg . ' ' . $did2);
|
||||
return;
|
||||
}
|
||||
|
||||
$salt = random_string(32);
|
||||
$password = $salt . ',' . hash('whirlpool', $salt . $password);
|
||||
|
||||
// accept tos
|
||||
if(! x($_POST,'tos')) {
|
||||
// msg!
|
||||
notice(t('Terms of Service not accepted') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$policy = get_config('system','register_policy');
|
||||
$invonly = get_config('system','invitation_only');
|
||||
$invalso = get_config('system','invitation_also');
|
||||
|
||||
switch($policy) {
|
||||
|
||||
|
||||
case REGISTER_OPEN:
|
||||
$flags = ACCOUNT_OK;
|
||||
break;
|
||||
|
||||
|
||||
case REGISTER_APPROVE:
|
||||
$flags = ACCOUNT_BLOCKED | ACCOUNT_PENDING;
|
||||
$flags = ACCOUNT_PENDING;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
case REGISTER_CLOSED:
|
||||
if(! is_site_admin()) {
|
||||
@@ -83,164 +203,278 @@ class Register extends Controller {
|
||||
$flags = ACCOUNT_BLOCKED;
|
||||
break;
|
||||
}
|
||||
|
||||
if($email_verify && $policy == REGISTER_OPEN)
|
||||
$flags = $flags | ACCOUNT_UNVERIFIED;
|
||||
|
||||
|
||||
if((! $_POST['password']) || ($_POST['password'] !== $_POST['password2'])) {
|
||||
notice( t('Passwords do not match.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$arr = $_POST;
|
||||
|
||||
if($email_verify && ($policy == REGISTER_OPEN || $policy == REGISTER_APPROVE))
|
||||
$flags = ($flags | ACCOUNT_UNVERIFIED);
|
||||
|
||||
// $arr has $_POST;
|
||||
$arr['account_flags'] = $flags;
|
||||
|
||||
$result = create_account($arr);
|
||||
|
||||
if(! $result['success']) {
|
||||
notice($result['message']);
|
||||
return;
|
||||
}
|
||||
require_once('include/security.php');
|
||||
|
||||
|
||||
if($_REQUEST['name'])
|
||||
set_aconfig($result['account']['account_id'],'register','channel_name',$_REQUEST['name']);
|
||||
if($_REQUEST['nickname'])
|
||||
set_aconfig($result['account']['account_id'],'register','channel_address',$_REQUEST['nickname']);
|
||||
if($_REQUEST['permissions_role'])
|
||||
set_aconfig($result['account']['account_id'],'register','permissions_role',$_REQUEST['permissions_role']);
|
||||
|
||||
|
||||
$using_invites = intval(get_config('system','invitation_only'));
|
||||
$num_invites = intval(get_config('system','number_invites'));
|
||||
$invite_code = ((x($_POST,'invite_code')) ? notags(trim($_POST['invite_code'])) : '');
|
||||
|
||||
if($using_invites && $invite_code) {
|
||||
q("delete from register where hash = '%s'", dbesc($invite_code));
|
||||
// @FIXME - this also needs to be considered when using 'invites_remaining' in mod/invite.php
|
||||
set_aconfig($result['account']['account_id'],'system','invites_remaining',$num_invites);
|
||||
}
|
||||
|
||||
if($policy == REGISTER_OPEN ) {
|
||||
if($email_verify) {
|
||||
$res = verify_email_address($result);
|
||||
}
|
||||
else {
|
||||
$res = send_register_success_email($result['email'],$result['password']);
|
||||
}
|
||||
if($res) {
|
||||
if($invite_code) {
|
||||
info( t('Registration successful. Continue to create your first channel...') . EOL ) ;
|
||||
}
|
||||
else {
|
||||
info( t('Registration successful. Please check your email for validation instructions.') . EOL ) ;
|
||||
$now = datetime_convert();
|
||||
$well = false;
|
||||
|
||||
// s3
|
||||
if ($invite_code) {
|
||||
|
||||
if ($invonly || $invalso) {
|
||||
|
||||
$reg = q("SELECT * from register WHERE reg_vital = 1 AND reg_didx = 'i' AND reg_hash = '%s'",
|
||||
dbesc($invite_code)
|
||||
);
|
||||
|
||||
if ($reg && count($reg) == 1) {
|
||||
$reg = $reg[0];
|
||||
if ($reg['reg_email'] == ($email)) {
|
||||
|
||||
if ($reg['reg_startup'] <= $now && $reg['reg_expires'] >= $now) {
|
||||
|
||||
if ($auto_create) {
|
||||
$reonar['chan.name'] = $name;
|
||||
$reonar['chan.did1'] = $nick;
|
||||
}
|
||||
|
||||
q("UPDATE register set reg_pass = '%s', reg_stuff = '%s' WHERE reg_id = '%s'",
|
||||
dbesc($password),
|
||||
dbesc(json_encode($reonar)),
|
||||
intval($reg['reg_id'])
|
||||
);
|
||||
|
||||
$msg = t('Invitation code succesfully applied');
|
||||
zar_log('ZAR0237I ' . $msg) . ', ' . $email;
|
||||
// msg!
|
||||
info($msg . EOL);
|
||||
|
||||
|
||||
// the invitecode has verified us and we have all the info we need
|
||||
// take the shortcut.
|
||||
|
||||
$_SESSION['zar']['invite_in_progress'] = true;
|
||||
|
||||
$mod = new Regate();
|
||||
$_REQUEST['form_security_token'] = get_form_security_token("regate");
|
||||
App::$argc = 2;
|
||||
App::$argv[0] = 'regate';
|
||||
App::$argv[1] = bin2hex($reg['reg_did2']) . 'i';
|
||||
return $mod->post();
|
||||
|
||||
} else {
|
||||
// msg!
|
||||
notice(t('Invitation not in time or too late') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// no match email adr
|
||||
$msg = t('Invitation email failed');
|
||||
zar_log('ZAR0235S ' . $msg);
|
||||
notice($msg . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// no match invitecode
|
||||
$msg = t('Invitation code failed') ;
|
||||
zar_log('ZAR0234S ' . $msg);
|
||||
notice( $msg . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($policy == REGISTER_APPROVE) {
|
||||
$res = send_reg_approval_email($result);
|
||||
if($res) {
|
||||
info( t('Your registration is pending approval by the site owner.') . EOL ) ;
|
||||
}
|
||||
else {
|
||||
notice( t('Your registration can not be processed.') . EOL);
|
||||
}
|
||||
goaway(z_root());
|
||||
}
|
||||
|
||||
if($email_verify) {
|
||||
goaway(z_root() . '/email_validation/' . bin2hex($result['email']));
|
||||
}
|
||||
|
||||
// fall through and authenticate if no approvals or verifications were required.
|
||||
|
||||
authenticate_success($result['account'],null,true,false,true);
|
||||
|
||||
$new_channel = false;
|
||||
$next_page = 'new_channel';
|
||||
|
||||
if(get_config('system','auto_channel_create')) {
|
||||
$new_channel = auto_channel_create($result['account']['account_id']);
|
||||
if($new_channel['success']) {
|
||||
$channel_id = $new_channel['channel']['channel_id'];
|
||||
change_channel($channel_id);
|
||||
$next_page = '~';
|
||||
}
|
||||
else
|
||||
$new_channel = false;
|
||||
}
|
||||
|
||||
$x = get_config('system','workflow_register_next');
|
||||
if($x) {
|
||||
$next_page = $x;
|
||||
$_SESSION['workflow'] = true;
|
||||
}
|
||||
|
||||
unset($_SESSION['login_return_url']);
|
||||
goaway(z_root() . '/' . $next_page);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
$registration_is = '';
|
||||
$other_sites = '';
|
||||
|
||||
if(intval(get_config('system','register_policy')) === REGISTER_CLOSED) {
|
||||
if(intval(get_config('system','directory_mode')) === DIRECTORY_MODE_STANDALONE) {
|
||||
notice( t('Registration on this hub is disabled.') . EOL);
|
||||
} else {
|
||||
notice(t('Invitations are not available') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$mod = new Pubsites();
|
||||
}
|
||||
else {
|
||||
if (!$invonly) {
|
||||
$well = true;
|
||||
}
|
||||
else {
|
||||
$msg = t('Registration on this hub is by invitation only') . EOL;
|
||||
notice($msg);
|
||||
zar_log('ZAR0233E ' . $msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// check max daily registrations after we have dealt with the invitecode
|
||||
if (self::check_reg_limits()['is']) {
|
||||
notice('Max registrations per day exceeded.');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($well) {
|
||||
|
||||
if($policy == REGISTER_OPEN || $policy == REGISTER_APPROVE ) {
|
||||
|
||||
$cfgdelay = get_config('system', 'register_delay', '0i');
|
||||
$reg_delayed = calculate_adue( $cfgdelay );
|
||||
$regdelay = (($reg_delayed) ? datetime_convert(date_default_timezone_get(), 'UTC', $reg_delayed['due']) : $now);
|
||||
|
||||
$cfgexpire = get_config('system', 'register_expire', '3d');
|
||||
$reg_expires = calculate_adue( $cfgexpire );
|
||||
$regexpire = (($reg_expires) ? datetime_convert(date_default_timezone_get(), 'UTC', $reg_expires['due']) : datetime_convert('UTC', 'UTC', 'now + 99 years'));
|
||||
|
||||
// handle an email request that will be verified or an ivitation associated with an email address
|
||||
if ($email > '' && $email_verify) {
|
||||
// enforce in case of icdone
|
||||
$flags |= ACCOUNT_UNVERIFIED;
|
||||
$empin = $pass2 = random_string(24);
|
||||
$did2 = $email;
|
||||
$didx = 'e';
|
||||
|
||||
push_lang(($reg['lang']) ? $reg['lang'] : App::$language);
|
||||
$reonar['from'] = get_config('system', 'from_email');
|
||||
$reonar['to'] = $email;
|
||||
$reonar['subject'] = sprintf( t('Registration confirmation for %s'), get_config('system','sitename'));
|
||||
$reonar['txttemplate']= replace_macros(get_intltext_template('register_verify_member.tpl'),
|
||||
[
|
||||
'$sitename' => get_config('system','sitename'),
|
||||
'$siteurl' => z_root(),
|
||||
'$email' => $email,
|
||||
'$timeframe' => [$regdelay, $regexpire],
|
||||
'$mail' => bin2hex($email) . 'e',
|
||||
'$ko' => bin2hex(substr($empin,0,4)),
|
||||
'$hash' => $empin
|
||||
]
|
||||
);
|
||||
pop_lang();
|
||||
zar_reg_mail($reonar);
|
||||
|
||||
} else {
|
||||
// that is an anonymous request without email or with email not to verify
|
||||
$acpin = $pass2 = rand(100000,999999);
|
||||
$did2 = rand(10,99);
|
||||
$didx = 'a';
|
||||
// enforce delayed verify
|
||||
$flags = ($flags | ACCOUNT_UNVERIFIED);
|
||||
if ($email) {
|
||||
$reonar['email.untrust'] = $email;
|
||||
$reonar['email.comment'] = 'received, but no need for';
|
||||
}
|
||||
}
|
||||
|
||||
if ($auto_create) {
|
||||
$reonar['chan.name'] = $name;
|
||||
$reonar['chan.did1'] = $nick;
|
||||
}
|
||||
|
||||
if ($policy == REGISTER_APPROVE) {
|
||||
$reonar['msg'] = $register_msg;
|
||||
}
|
||||
|
||||
$reg = q("INSERT INTO register ("
|
||||
. "reg_flags,reg_didx,reg_did2,reg_hash,reg_created,reg_startup,reg_expires,"
|
||||
. "reg_email,reg_pass,reg_lang,reg_atip,reg_stuff)"
|
||||
. " VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
|
||||
intval($flags),
|
||||
dbesc($didx),
|
||||
dbesc($did2),
|
||||
dbesc($pass2),
|
||||
dbesc($now),
|
||||
dbesc($regdelay),
|
||||
dbesc($regexpire),
|
||||
dbesc($email),
|
||||
dbesc($password),
|
||||
dbesc(App::$language),
|
||||
dbesc($ip),
|
||||
dbesc(json_encode($reonar))
|
||||
);
|
||||
|
||||
if ($didx == 'a') {
|
||||
|
||||
$lid = q("SELECT reg_id FROM register WHERE reg_vital = 1 AND reg_did2 = '%s' AND reg_pass = '%s' ",
|
||||
dbesc($did2),
|
||||
dbesc($password)
|
||||
);
|
||||
|
||||
if ($lid && count($lid) == 1 ) {
|
||||
|
||||
$didnew = ( $lid[0]['reg_id'] . $did2 )
|
||||
. ( substr( base_convert( md5( $lid[0]['reg_id'] . $did2 ), 16, 10 ),-2 ) );
|
||||
|
||||
$reg = q("UPDATE register SET reg_did2 = CONCAT('d','%s') WHERE reg_id = %d ",
|
||||
dbesc($didnew), intval($lid[0]['reg_id'])
|
||||
);
|
||||
|
||||
zar_log( 'ZAR0239A ' . t('New register request') . ' d' . $didnew . ', '
|
||||
. $regdelay . ' - ' . $regexpire);
|
||||
|
||||
if($reg_delayed) {
|
||||
// this could be removed to make registration harder
|
||||
$_SESSION['zar']['id'] = 'd' . $didnew;
|
||||
$_SESSION['zar']['pin'] = $pass2;
|
||||
$_SESSION['zar']['delayed'] = true;
|
||||
$_SESSION['zar']['regdelay'] = datetime_convert('UTC', 'UTC', $regdelay, 'c');
|
||||
$_SESSION['zar']['regexpire'] = datetime_convert('UTC', 'UTC', $regexpire, 'c');
|
||||
}
|
||||
else {
|
||||
$_SESSION['zar']['pin'] = $pass2;
|
||||
}
|
||||
|
||||
goaway(z_root() . '/regate/' . bin2hex('d' . $didnew) . 'a' );
|
||||
}
|
||||
else {
|
||||
$msg = t('Error creating dId A');
|
||||
notice( $msg );
|
||||
zar_log( 'ZAR0239D,' . $msg . ' ' . $did2);
|
||||
}
|
||||
}
|
||||
goaway(z_root() . '/regate/' . bin2hex($email) . $didx );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
$registration_is = '';
|
||||
$other_sites = '';
|
||||
|
||||
if(intval(get_config('system','register_policy')) === REGISTER_CLOSED) {
|
||||
if(intval(get_config('system','directory_mode')) === DIRECTORY_MODE_STANDALONE) {
|
||||
notice(t('Registration on this hub is disabled.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$mod = new Pubsites();
|
||||
return $mod->get();
|
||||
}
|
||||
|
||||
|
||||
if(intval(get_config('system','register_policy')) == REGISTER_APPROVE) {
|
||||
$registration_is = t('Registration on this hub is by approval only.');
|
||||
$other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>');
|
||||
$other_sites = '<a href="pubsites">' . t('Register at another affiliated hub in case when prefered') . '</a>';
|
||||
}
|
||||
|
||||
$duty = zar_register_dutystate();
|
||||
|
||||
if (!get_config('system', 'register_duty_jso')) {
|
||||
// if not yet configured default to true
|
||||
$duty = array( 'isduty' => true, 'atfrm' => '', 'nowfmt' => '');
|
||||
}
|
||||
|
||||
$invitations = false;
|
||||
|
||||
if(intval(get_config('system','invitation_only'))) {
|
||||
$invitations = true;
|
||||
$registration_is = t('Registration on this hub is by invitation only.');
|
||||
$other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>');
|
||||
}
|
||||
|
||||
$max_dailies = intval(get_config('system','max_daily_registrations'));
|
||||
if($max_dailies) {
|
||||
$r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('1 day')
|
||||
);
|
||||
if($r && $r[0]['total'] >= $max_dailies) {
|
||||
logger('max daily registrations exceeded.');
|
||||
notice( t('This site has exceeded the number of allowed daily account registrations. Please try again tomorrow.') . EOL);
|
||||
return;
|
||||
}
|
||||
$other_sites = '<a href="pubsites">' . t('Register at another affiliated hub') . '</a>';
|
||||
} elseif (intval(get_config('system','invitation_also'))) {
|
||||
$invitations = true;
|
||||
}
|
||||
|
||||
$privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "");
|
||||
|
||||
$perm_roles = \Zotlabs\Access\PermissionRoles::roles();
|
||||
$opal = self::check_reg_limits();
|
||||
if ( $opal['is'])
|
||||
$duty['atform'] = 'disabled';
|
||||
|
||||
// Configurable terms of service link
|
||||
|
||||
$tosurl = get_config('system','tos_url');
|
||||
if(! $tosurl)
|
||||
$tosurl = z_root() . '/help/TermsOfService';
|
||||
|
||||
|
||||
$toslink = '<a href="' . $tosurl . '" target="_blank">' . t('Terms of Service') . '</a>';
|
||||
|
||||
|
||||
// Configurable whether to restrict age or not - default is based on international legal requirements
|
||||
// This can be relaxed if you are on a restricted server that does not share with public servers
|
||||
|
||||
|
||||
if(get_config('system','no_age_restriction')) {
|
||||
$label_tos = sprintf( t('I accept the %s for this website'), $toslink);
|
||||
}
|
||||
@@ -253,50 +487,96 @@ class Register extends Controller {
|
||||
}
|
||||
|
||||
$enable_tos = 1 - intval(get_config('system','no_termsofservice'));
|
||||
|
||||
$email = array('email', t('Your email address'), ((x($_REQUEST,'email')) ? strip_tags(trim($_REQUEST['email'])) : ""));
|
||||
$password = array('password', t('Choose a password'), '');
|
||||
$password2 = array('password2', t('Please re-enter your password'), '');
|
||||
$invite_code = array('invite_code', t('Please enter your invitation code'), ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : ""));
|
||||
$name = array('name', t('Your Name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Real names are preferred.'));
|
||||
$nickhub = '@' . str_replace(array('http://','https://','/'), '', get_config('system','baseurl'));
|
||||
$nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub));
|
||||
$role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role for your usage needs and privacy requirements.') . ' <a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles);
|
||||
$tos = array('tos', $label_tos, '', '', array(t('no'),t('yes')));
|
||||
|
||||
|
||||
$auto_create = (get_config('system','auto_channel_create') ? true : false);
|
||||
$default_role = get_config('system','default_permissions_role');
|
||||
$auto_create = get_config('system', 'auto_channel_create', 1);
|
||||
$email_verify = get_config('system','verify_email');
|
||||
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
$o = replace_macros(get_markup_template('register.tpl'), array(
|
||||
|
||||
$emailval = ((x($_REQUEST,'email')) ? strip_tags(trim($_REQUEST['email'])) : "");
|
||||
$email = ['email',
|
||||
t('Your email address'),
|
||||
$emailval,
|
||||
(($email_verify) ? t('Required') : t('Optional')),
|
||||
(($email_verify) ? '*' : ''),
|
||||
$duty['atform']
|
||||
];
|
||||
|
||||
$password = array('password', t('Choose a password'), '', '', '', $duty['atform']);
|
||||
$password2 = array('password2', t('Please re-enter your password'), '', '', '', $duty['atform']);
|
||||
|
||||
$invite_code = array('invite_code', t('Please enter your invitation code'), ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : ""));
|
||||
|
||||
$name = array('name', t('Your name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Real name is preferred'), '', '', $duty['atform']);
|
||||
$nickhub = '@' . str_replace(array('http://','https://','/'), '', get_config('system','baseurl'));
|
||||
$nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), t('Your nickname will be used to create an easy to remember channel address'), '', '', $duty['atform']);
|
||||
|
||||
$tos = array('tos', $label_tos, ((x($_REQUEST,'tos')) ? $_REQUEST['tos'] : ''), '', [t('No'),t('Yes')], $duty['atform']);
|
||||
|
||||
$register_msg = ['register_msg', t('Why do you want to join this hub?'), ((x($_REQUEST,'register_msg')) ? $_REQUEST['register_msg'] : ''), t('This will help to review your registration')];
|
||||
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
$o = replace_macros(get_markup_template('register.tpl'), array(
|
||||
'$form_security_token' => get_form_security_token("register"),
|
||||
'$title' => t('Registration'),
|
||||
'$reg_is' => $registration_is,
|
||||
'$register_msg' => $register_msg,
|
||||
'$registertext' => bbcode(get_config('system','register_text')),
|
||||
'$other_sites' => $other_sites,
|
||||
'$msg' => $opal['msg'],
|
||||
'$invitations' => $invitations,
|
||||
'$invite_code' => $invite_code,
|
||||
'$haveivc' => t('I have an invite code'),
|
||||
'$now' => $duty['nowfmt'],
|
||||
'$atform' => $duty['atform'],
|
||||
'$auto_create' => $auto_create,
|
||||
'$name' => $name,
|
||||
'$role' => $role,
|
||||
'$default_role' => $default_role,
|
||||
'$nickname' => $nickname,
|
||||
'$enable_tos' => $enable_tos,
|
||||
'$tos' => $tos,
|
||||
'$email' => $email,
|
||||
'$validate' => $validate,
|
||||
'$validate_link'=> $validate_link,
|
||||
'$validate_here'=> $validate_here,
|
||||
'$pass1' => $password,
|
||||
'$pass2' => $password2,
|
||||
'$submit' => t('Register'),
|
||||
'$verify_note' => (($email_verify) ? t('This site requires email verification. After completing this form, please check your email for further instructions.') : ''),
|
||||
'$nickhub' => $nickhub
|
||||
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function check_reg_limits() {
|
||||
// check against register, account
|
||||
$rear = array( 'is' => false, 'rn' => 0, 'an' => 0, 'msg' => '' );
|
||||
|
||||
$max_dailies = intval(get_config('system', 'max_daily_registrations', 50));
|
||||
|
||||
if ($max_dailies) {
|
||||
|
||||
$r = q("SELECT COUNT(reg_id) AS nr FROM register WHERE reg_vital = 1 AND reg_created > %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('1 day')
|
||||
);
|
||||
|
||||
$rear['is'] = ( $r && $r[0]['nr'] >= $max_dailies ) ? true : false;
|
||||
$rear['rn'] = $r[0]['nr'];
|
||||
|
||||
if (!$rear['is']) {
|
||||
$r = q("SELECT COUNT(account_id) AS nr FROM account WHERE account_created > %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('1 day')
|
||||
);
|
||||
|
||||
$rear['is'] = ( $r && ($r[0]['nr'] + $rear['rn']) >= $max_dailies ) ? true : false;
|
||||
$rear['ra'] = $r[0]['nr'];
|
||||
}
|
||||
|
||||
if ( $rear['is']) {
|
||||
$rear['msg'] = t('This site has exceeded the number of allowed daily account registrations.');
|
||||
zar_log('ZAR0333W ' . $rear['msg']);
|
||||
$rear['is'] = true;
|
||||
}
|
||||
}
|
||||
return $rear;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class Search extends Controller {
|
||||
$o .= search($search, 'search-box', '/search', ((local_channel()) ? true : false));
|
||||
|
||||
if (local_channel() && strpos($search, 'https://') === 0 && !$update && !$load) {
|
||||
$j = Activity::fetch($search, App::get_channel());
|
||||
$j = Activity::fetch(punify($search), App::get_channel());
|
||||
if ($j) {
|
||||
$AS = new ActivityStreams($j);
|
||||
if ($AS->is_valid()) {
|
||||
@@ -101,7 +101,7 @@ class Search extends Controller {
|
||||
}
|
||||
|
||||
// look for a naked webbie
|
||||
if (strpos($search, '@') !== false) {
|
||||
if (strpos($search,'@') !== false && strpos($search,'http') !== 0) {
|
||||
goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,20 +15,23 @@ class Account {
|
||||
|
||||
$account = \App::get_account();
|
||||
if($email != $account['account_email']) {
|
||||
if(! validate_email($email))
|
||||
$errs[] = t('Not valid email.');
|
||||
$adm = trim(get_config('system','admin_email'));
|
||||
if(($adm) && (strcasecmp($email,$adm) == 0)) {
|
||||
$errs[] = t('Protected email address. Cannot change to that email.');
|
||||
$email = \App::$account['account_email'];
|
||||
}
|
||||
if(! $errs) {
|
||||
$r = q("update account set account_email = '%s' where account_id = %d",
|
||||
dbesc($email),
|
||||
intval($account['account_id'])
|
||||
);
|
||||
if(! $r)
|
||||
$errs[] = t('System failure storing new email. Please try again.');
|
||||
// a DId2 not an email addr does not allow to change to email addr
|
||||
if (strpos($email, '@') > 0) {
|
||||
if(! validate_email($email))
|
||||
$errs[] = t('Not valid email.');
|
||||
$adm = trim(get_config('system','admin_email'));
|
||||
if(($adm) && (strcasecmp($email,$adm) == 0)) {
|
||||
$errs[] = t('Protected email address. Cannot change to that email.');
|
||||
$email = \App::$account['account_email'];
|
||||
}
|
||||
if(! $errs) {
|
||||
$r = q("update account set account_email = '%s' where account_id = %d",
|
||||
dbesc($email),
|
||||
intval($account['account_id'])
|
||||
);
|
||||
if(! $r)
|
||||
$errs[] = t('System failure storing new email. Please try again.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +95,7 @@ class Account {
|
||||
call_hooks('account_settings', $account_settings);
|
||||
|
||||
$email = \App::$account['account_email'];
|
||||
$attremail = (!strpos($email, '@')) ? 'disabled="disabled"' : '';
|
||||
|
||||
$tpl = get_markup_template("settings_account.tpl");
|
||||
$o .= replace_macros($tpl, array(
|
||||
@@ -101,7 +105,7 @@ class Account {
|
||||
'$password1'=> array('npassword', t('Enter New Password'), '', ''),
|
||||
'$password2'=> array('confirm', t('Confirm New Password'), '', t('Leave password fields blank unless changing')),
|
||||
'$submit' => t('Submit'),
|
||||
'$email' => array('email', t('Email Address:'), $email, ''),
|
||||
'$email' => array('email', t('DId2 or Email Address:'), $email, '', '', $attremail),
|
||||
'$removeme' => t('Remove Account'),
|
||||
'$removeaccount' => t('Remove this account including all its channels'),
|
||||
'$account_settings' => $account_settings
|
||||
|
||||
@@ -47,7 +47,6 @@ class Sse extends Controller {
|
||||
|
||||
self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify');
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$sleep_seconds = 3;
|
||||
|
||||
self::$sse_enabled = get_config('system', 'sse_enabled', 0);
|
||||
|
||||
@@ -6,6 +6,7 @@ use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Enotify;
|
||||
use Zotlabs\Lib\XConfig;
|
||||
|
||||
class Sse_bs extends Controller {
|
||||
|
||||
@@ -101,12 +102,13 @@ class Sse_bs extends Controller {
|
||||
self::bs_files(),
|
||||
self::bs_mail(),
|
||||
self::bs_all_events(),
|
||||
self::bs_register()
|
||||
self::bs_register(),
|
||||
self::bs_info_notice()
|
||||
);
|
||||
|
||||
set_xconfig(self::$ob_hash, 'sse', 'timestamp', datetime_convert());
|
||||
set_xconfig(self::$ob_hash, 'sse', 'notifications', []); // reset the cache
|
||||
set_xconfig(self::$ob_hash, 'sse', 'language', App::$language);
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', datetime_convert());
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'language', App::$language);
|
||||
|
||||
json_return_and_die($result);
|
||||
}
|
||||
@@ -686,12 +688,15 @@ class Sse_bs extends Controller {
|
||||
if(! self::$uid && ! is_site_admin())
|
||||
return $result;
|
||||
|
||||
$policy = intval(get_config('system','register_policy'));
|
||||
if(($policy & REGISTER_APPROVE) != REGISTER_APPROVE)
|
||||
return $result;
|
||||
|
||||
if(! (self::$vnotify & VNOTIFY_REGISTER))
|
||||
return $result;
|
||||
|
||||
$r = q("SELECT account_email, account_created from account where (account_flags & %d) > 0",
|
||||
intval(ACCOUNT_PENDING)
|
||||
);
|
||||
$r = get_pending_accounts();
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$result['register']['notifications'][] = Enotify::format_register($rr);
|
||||
@@ -703,4 +708,22 @@ class Sse_bs extends Controller {
|
||||
|
||||
}
|
||||
|
||||
function bs_info_notice() {
|
||||
|
||||
$result['notice']['notifications'] = [];
|
||||
$result['info']['notifications'] = [];
|
||||
|
||||
$r = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
|
||||
|
||||
if(isset($r['notice']))
|
||||
$result['notice']['notifications'] = $r['notice']['notifications'];
|
||||
|
||||
if(isset($r['info']))
|
||||
$result['info']['notifications'] = $r['info']['notifications'];
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,17 +15,17 @@ class Suggest extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Suggest Channels'))
|
||||
return;
|
||||
|
||||
|
||||
if(x($_GET,'ignore')) {
|
||||
q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
|
||||
intval(local_channel()),
|
||||
dbesc($_GET['ignore'])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
@@ -45,22 +45,22 @@ class Suggest extends \Zotlabs\Web\Controller {
|
||||
$o = '';
|
||||
|
||||
nav_set_selected('Suggest Channels');
|
||||
|
||||
|
||||
$_SESSION['return_url'] = z_root() . '/' . \App::$cmd;
|
||||
|
||||
|
||||
$r = suggestion_query(local_channel(),get_observer_hash());
|
||||
|
||||
|
||||
if(! $r) {
|
||||
info( t('No suggestions available. If this is a new site, please try again in 24 hours.'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$arr = array();
|
||||
|
||||
|
||||
foreach($r as $rr) {
|
||||
|
||||
$connlnk = z_root() . '/follow/?url=' . $rr['xchan_addr'];
|
||||
|
||||
|
||||
$connlnk = z_root() . '/follow?f=&url=' . $rr['xchan_addr'];
|
||||
|
||||
$arr[] = array(
|
||||
'url' => chanlink_url($rr['xchan_url']),
|
||||
'common' => $rr['total'],
|
||||
@@ -73,15 +73,15 @@ class Suggest extends \Zotlabs\Web\Controller {
|
||||
'ignore' => t('Ignore/Hide')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$o = replace_macros(get_markup_template('suggest_page.tpl'),array(
|
||||
'$title' => t('Channel Suggestions'),
|
||||
'$entries' => $arr
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ class Wfinger extends \Zotlabs\Web\Controller {
|
||||
$scheme = 'https';
|
||||
elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443))
|
||||
$scheme = 'https';
|
||||
elseif(x($_SERVER,'HTTP_X_FORWARDED_PROTO') && ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'))
|
||||
$scheme = 'https';
|
||||
|
||||
$zot = intval($_REQUEST['zot']);
|
||||
|
||||
|
||||
@@ -127,7 +127,6 @@ class Wiki extends Controller {
|
||||
|
||||
$resource_id = argv(4);
|
||||
$w = NativeWiki::get_wiki($owner['channel_id'],$observer_hash,$resource_id);
|
||||
|
||||
// $w = NativeWiki::get_wiki($owner,$observer_hash,$resource_id);
|
||||
if(! $w['htmlName']) {
|
||||
notice(t('Error retrieving wiki') . EOL);
|
||||
@@ -218,12 +217,12 @@ class Wiki extends Controller {
|
||||
'$name' => t('Name'),
|
||||
'$type' => t('Type'),
|
||||
'$unlocked' => t('Any type'),
|
||||
'$lockstate' => $x['lockstate'],
|
||||
'$acl' => $x['acl'],
|
||||
'$allow_cid' => $x['allow_cid'],
|
||||
'$allow_gid' => $x['allow_gid'],
|
||||
'$deny_cid' => $x['deny_cid'],
|
||||
'$deny_gid' => $x['deny_gid'],
|
||||
'$lockstate' => (x($x,'lockstate') ? $x['lockstate'] : ''),
|
||||
'$acl' => (x($x,'acl') ? $x['acl'] : ''),
|
||||
'$allow_cid' => (x($x,'allow_cid') ? $x['allow_cid'] : ''),
|
||||
'$allow_gid' => (x($x,'allow_gid') ? $x['allow_gid'] : ''),
|
||||
'$deny_cid' => (x($x,'deny_cid') ? $x['deny_cid'] : ''),
|
||||
'$deny_gid' => (x($x,'deny_gid') ? $x['deny_gid'] : ''),
|
||||
'$typelock' => array('typelock', t('Lock content type'), '', '', array(t('No'), t('Yes'))),
|
||||
'$notify' => array('postVisible', t('Create a status post for this wiki'), '', '', array(t('No'), t('Yes'))),
|
||||
'$edit_wiki_name' => t('Edit Wiki Name')
|
||||
@@ -508,7 +507,7 @@ class Wiki extends Controller {
|
||||
notice( t('Wiki created, but error creating Home page.'));
|
||||
goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName']));
|
||||
}
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'],$homePage['item_id'],$r['item']['resource_id']);
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'], $homePage['item_id'], $r['item']['resource_id']);
|
||||
goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName']) . '/' . NativeWiki::name_encode($homePage['page']['urlName']));
|
||||
}
|
||||
else {
|
||||
@@ -542,7 +541,6 @@ class Wiki extends Controller {
|
||||
}
|
||||
|
||||
$wiki = NativeWiki::exists_by_name($owner['channel_id'], $arr['urlName']);
|
||||
|
||||
if($wiki['resource_id']) {
|
||||
|
||||
$arr['resource_id'] = $wiki['resource_id'];
|
||||
@@ -552,7 +550,7 @@ class Wiki extends Controller {
|
||||
|
||||
$r = NativeWiki::update_wiki($owner['channel_id'], $observer_hash, $arr, $acl);
|
||||
if($r['success']) {
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'],$r['item_id'],$r['item']['resource_id']);
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'], $r['item_id'], $r['item']['resource_id']);
|
||||
goaway(z_root() . '/wiki/' . $nick);
|
||||
}
|
||||
else {
|
||||
@@ -576,7 +574,7 @@ class Wiki extends Controller {
|
||||
$resource_id = $_POST['resource_id'];
|
||||
$deleted = NativeWiki::delete_wiki($owner['channel_id'],$observer_hash,$resource_id);
|
||||
if ($deleted['success']) {
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'],$deleted['item_id'],$resource_id);
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'], 0, $resource_id);
|
||||
json_return_and_die(array('message' => '', 'success' => true));
|
||||
}
|
||||
else {
|
||||
@@ -611,18 +609,17 @@ class Wiki extends Controller {
|
||||
}
|
||||
|
||||
$page = NativeWikiPage::create_page($owner['channel_id'],$observer_hash, $name, $resource_id, $mimetype);
|
||||
|
||||
if($page['item_id']) {
|
||||
$commit = NativeWikiPage::commit(array(
|
||||
|
||||
$commit = NativeWikiPage::commit([
|
||||
'commit_msg' => t('New page created'),
|
||||
'resource_id' => $resource_id,
|
||||
'channel_id' => $owner['channel_id'],
|
||||
'observer_hash' => $observer_hash,
|
||||
'pageUrlName' => $name
|
||||
));
|
||||
|
||||
]);
|
||||
if($commit['success']) {
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id);
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id);
|
||||
//json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . urlencode($page['wiki']['urlName']) . '/' . urlencode($page['page']['urlName']), 'success' => true));
|
||||
json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . $page['wiki']['urlName'] . '/' . $page['page']['urlName'], 'success' => true));
|
||||
}
|
||||
@@ -680,20 +677,25 @@ class Wiki extends Controller {
|
||||
json_return_and_die(array('success' => false));
|
||||
}
|
||||
|
||||
$saved = NativeWikiPage::save_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'content' => $content));
|
||||
|
||||
$saved = NativeWikiPage::save_page([
|
||||
'channel_id' => $owner['channel_id'],
|
||||
'observer_hash' => $observer_hash,
|
||||
'resource_id' => $resource_id,
|
||||
'pageUrlName' => $pageUrlName,
|
||||
'content' => $content
|
||||
]);
|
||||
if($saved['success']) {
|
||||
$commit = NativeWikiPage::commit(array(
|
||||
|
||||
$commit = NativeWikiPage::commit([
|
||||
'commit_msg' => $commitMsg,
|
||||
'pageUrlName' => $pageUrlName,
|
||||
'resource_id' => $resource_id,
|
||||
'channel_id' => $owner['channel_id'],
|
||||
'observer_hash' => $observer_hash,
|
||||
'revision' => (-1)
|
||||
));
|
||||
|
||||
]);
|
||||
if($commit['success']) {
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id);
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id);
|
||||
json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true , 'content' => $content));
|
||||
}
|
||||
else {
|
||||
@@ -738,9 +740,9 @@ class Wiki extends Controller {
|
||||
if ($pageUrlName === 'Home') {
|
||||
json_return_and_die(array('message' => t('Cannot delete Home'),'success' => false));
|
||||
}
|
||||
|
||||
// Determine if observer has permission to delete pages
|
||||
// currently just allow page owner
|
||||
|
||||
if((! local_channel()) || (local_channel() != $owner['channel_id'])) {
|
||||
logger('Wiki write permission denied. ' . EOL);
|
||||
json_return_and_die(array('success' => false));
|
||||
@@ -752,9 +754,14 @@ class Wiki extends Controller {
|
||||
json_return_and_die(array('success' => false));
|
||||
}
|
||||
|
||||
$deleted = NativeWikiPage::delete_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
|
||||
$deleted = NativeWikiPage::delete_page([
|
||||
'channel_id' => $owner['channel_id'],
|
||||
'observer_hash' => $observer_hash,
|
||||
'resource_id' => $resource_id,
|
||||
'pageUrlName' => $pageUrlName
|
||||
]);
|
||||
if($deleted['success']) {
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id);
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'], 0, $resource_id);
|
||||
json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true));
|
||||
}
|
||||
else {
|
||||
@@ -768,18 +775,25 @@ class Wiki extends Controller {
|
||||
$resource_id = $_POST['resource_id'];
|
||||
$pageUrlName = $_POST['name'];
|
||||
$commitHash = $_POST['commitHash'];
|
||||
// Determine if observer has permission to revert pages
|
||||
|
||||
// Determine if observer has permission to revert pages
|
||||
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
|
||||
if(! $perms['write']) {
|
||||
logger('Wiki write permission denied.' . EOL);
|
||||
json_return_and_die(array('success' => false));
|
||||
}
|
||||
|
||||
$reverted = NativeWikiPage::revert_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'commitHash' => $commitHash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
|
||||
$reverted = NativeWikiPage::revert_page([
|
||||
'channel_id' => $owner['channel_id'],
|
||||
'observer_hash' => $observer_hash,
|
||||
'commitHash' => $commitHash,
|
||||
'resource_id' => $resource_id,
|
||||
'pageUrlName' => $pageUrlName
|
||||
]);
|
||||
if($reverted['success']) {
|
||||
json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
json_return_and_die(array('content' => '', 'message' => 'Error reverting page', 'success' => false));
|
||||
}
|
||||
}
|
||||
@@ -826,18 +840,23 @@ class Wiki extends Controller {
|
||||
json_return_and_die(array('success' => false));
|
||||
}
|
||||
|
||||
$renamed = NativeWikiPage::rename_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'pageNewName' => $pageNewName));
|
||||
|
||||
$renamed = NativeWikiPage::rename_page([
|
||||
'channel_id' => $owner['channel_id'],
|
||||
'observer_hash' => $observer_hash,
|
||||
'resource_id' => $resource_id,
|
||||
'pageUrlName' => $pageUrlName,
|
||||
'pageNewName' => $pageNewName
|
||||
]);
|
||||
if($renamed['success']) {
|
||||
$commit = NativeWikiPage::commit(array(
|
||||
$commit = NativeWikiPage::commit([
|
||||
'channel_id' => $owner['channel_id'],
|
||||
'commit_msg' => 'Renamed ' . NativeWiki::name_decode($pageUrlName) . ' to ' . $renamed['page']['htmlName'],
|
||||
'resource_id' => $resource_id,
|
||||
'observer_hash' => $observer_hash,
|
||||
'pageUrlName' => $pageNewName
|
||||
));
|
||||
]);
|
||||
if($commit['success']) {
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id);
|
||||
NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id);
|
||||
json_return_and_die(array('name' => $renamed['page'], 'message' => 'Wiki git repo commit made', 'success' => true));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -330,6 +330,8 @@ class Comanche {
|
||||
$name = str_replace($mtch[0], '', $name);
|
||||
}
|
||||
}
|
||||
else
|
||||
$var = [];
|
||||
|
||||
if($channel_id) {
|
||||
$m = menu_fetch($name, $channel_id, get_observer_hash());
|
||||
@@ -408,7 +410,8 @@ class Comanche {
|
||||
}
|
||||
|
||||
//emit the block
|
||||
$o .= (($var['wrap'] == 'none') ? '' : '<div class="' . $class . '">');
|
||||
$wrap = (! x($var, 'wrap') || $var['wrap'] == 'none' ? false : true);
|
||||
$o .= ($wrap ? '' : '<div class="' . $class . '">');
|
||||
|
||||
if($r[0]['title'] && trim($r[0]['body']) != '$content') {
|
||||
$o .= '<h3>' . $r[0]['title'] . '</h3>';
|
||||
@@ -421,7 +424,7 @@ class Comanche {
|
||||
$o .= prepare_text($r[0]['body'], $r[0]['mimetype']);
|
||||
}
|
||||
|
||||
$o .= (($var['wrap'] == 'none') ? '' : '</div>');
|
||||
$o .= ($wrap ? '' : '</div>');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,16 +8,16 @@ use App;
|
||||
class SmartyTemplate implements TemplateEngine {
|
||||
|
||||
static $name ="smarty3";
|
||||
|
||||
|
||||
public function __construct() {
|
||||
|
||||
// Cannot use get_config() here because it is called during installation when there is no DB.
|
||||
// FIXME: this may leak private information such as system pathnames.
|
||||
|
||||
$basecompiledir = ((array_key_exists('smarty3_folder', App::$config['system']))
|
||||
$basecompiledir = ((array_key_exists('smarty3_folder', App::$config['system']))
|
||||
? App::$config['system']['smarty3_folder'] : '');
|
||||
if (! $basecompiledir) {
|
||||
$basecompiledir = str_replace('Zotlabs','',dirname(__dir__)) . "/" . TEMPLATE_BUILD_PATH;
|
||||
$basecompiledir = str_replace('Zotlabs','',dirname(__dir__)) . TEMPLATE_BUILD_PATH;
|
||||
}
|
||||
if (! is_dir($basecompiledir)) {
|
||||
@os_mkdir(TEMPLATE_BUILD_PATH, STORAGE_DEFAULT_PERMISSIONS, true);
|
||||
@@ -30,7 +30,7 @@ class SmartyTemplate implements TemplateEngine {
|
||||
}
|
||||
App::$config['system']['smarty3_folder'] = $basecompiledir;
|
||||
}
|
||||
|
||||
|
||||
// TemplateEngine interface
|
||||
|
||||
public function replace_macros($s, $r) {
|
||||
@@ -52,9 +52,9 @@ class SmartyTemplate implements TemplateEngine {
|
||||
}
|
||||
$s->assign($key, $value);
|
||||
}
|
||||
return $s->parsed($template);
|
||||
return $s->parsed($template);
|
||||
}
|
||||
|
||||
|
||||
public function get_markup_template($file, $root = '') {
|
||||
$template_file = theme_include($file, $root);
|
||||
if ($template_file) {
|
||||
@@ -62,7 +62,7 @@ class SmartyTemplate implements TemplateEngine {
|
||||
$template->filename = $template_file;
|
||||
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class SmartyTemplate implements TemplateEngine {
|
||||
$template = new SmartyInterface();
|
||||
$template->filename = $template_file;
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -125,10 +125,10 @@ class BasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
* Array with the values for the authenticated channel.
|
||||
* @return bool
|
||||
*/
|
||||
protected function setAuthenticated($r) {
|
||||
$this->channel_name = $r['channel_address'];
|
||||
$this->channel_id = $r['channel_id'];
|
||||
$this->channel_hash = $this->observer = $r['channel_hash'];
|
||||
protected function setAuthenticated($channel) {
|
||||
$this->channel_name = $channel['channel_address'];
|
||||
$this->channel_id = $channel['channel_id'];
|
||||
$this->channel_hash = $this->observer = $channel['channel_hash'];
|
||||
|
||||
if ($this->observer) {
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
@@ -139,8 +139,8 @@ class BasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
}
|
||||
}
|
||||
|
||||
$_SESSION['uid'] = $r['channel_id'];
|
||||
$_SESSION['account_id'] = $r['channel_account_id'];
|
||||
$_SESSION['uid'] = $channel['channel_id'];
|
||||
$_SESSION['account_id'] = $channel['channel_account_id'];
|
||||
$_SESSION['authenticated'] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
15
Zotlabs/Update/_1244.php
Normal file
15
Zotlabs/Update/_1244.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
require_once('include/account.php');
|
||||
|
||||
class _1244 {
|
||||
|
||||
function run() {
|
||||
|
||||
return verify_register_scheme();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
29
Zotlabs/Update/_1245.php
Normal file
29
Zotlabs/Update/_1245.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1245 {
|
||||
|
||||
function run() {
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_MYSQL) {
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
q("START TRANSACTION");
|
||||
|
||||
$r = dbq("create index hubloc_hash on hubloc (hubloc_hash)");
|
||||
|
||||
if($r) {
|
||||
q("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
q("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -250,7 +250,7 @@ class HTTPSig {
|
||||
static function convertKey($key) {
|
||||
|
||||
if(strstr($key,'RSA ')) {
|
||||
return rsatopem($key);
|
||||
return Keyutils::rsaToPem($key);
|
||||
}
|
||||
elseif(substr($key,0,5) === 'data:') {
|
||||
return Keyutils::convertSalmonKey($key);
|
||||
|
||||
@@ -29,34 +29,44 @@ class Session {
|
||||
/*
|
||||
* Set our session storage functions.
|
||||
*/
|
||||
|
||||
|
||||
if($this->custom_handler) {
|
||||
/* Custom handler (files, memached, redis..) */
|
||||
|
||||
$session_save_handler = strval(get_config('system', 'session_save_handler', Null));
|
||||
$session_save_path = strval(get_config('system', 'session_save_path', Null));
|
||||
$session_gc_probability = intval(get_config('system', 'session_gc_probability', 1));
|
||||
$session_gc_divisor = intval(get_config('system', 'session_gc_divisor', 100));
|
||||
if(!$session_save_handler || !$session_save_path) {
|
||||
logger('Session save handler or path not set.',LOGGER_NORMAL,LOG_ERR);
|
||||
|
||||
if(is_null($session_save_handler) || is_null($session_save_path)) {
|
||||
logger('Session save handler or path not set', LOGGER_NORMAL, LOG_ERR);
|
||||
}
|
||||
else {
|
||||
ini_set('session.save_handler', $session_save_handler);
|
||||
ini_set('session.save_path', $session_save_path);
|
||||
ini_set('session.gc_probability', $session_gc_probability);
|
||||
ini_set('session.gc_divisor', $session_gc_divisor);
|
||||
// Check if custom sessions backend exists
|
||||
$clsname = '\Zotlabs\Web\Session' . ucfirst(strtolower($session_save_handler));
|
||||
if (class_exists($clsname)) {
|
||||
$handler = new $clsname($session_save_path);
|
||||
}
|
||||
else {
|
||||
ini_set('session.save_handler', $session_save_handler);
|
||||
ini_set('session.save_path', $session_save_path);
|
||||
ini_set('session.gc_probability', intval(get_config('system', 'session_gc_probability', 1)));
|
||||
ini_set('session.gc_divisor', intval(get_config('system', 'session_gc_divisor', 100)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$handler = new \Zotlabs\Web\SessionHandler();
|
||||
$handler = new SessionHandler();
|
||||
}
|
||||
|
||||
if (isset($handler)) {
|
||||
|
||||
$this->handler = $handler;
|
||||
|
||||
$x = session_set_save_handler($handler,false);
|
||||
if(! $x)
|
||||
logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR);
|
||||
$x = session_set_save_handler($handler, false);
|
||||
if(! $x)
|
||||
logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR);
|
||||
}
|
||||
|
||||
|
||||
// Force cookies to be secure (https only) if this site is SSL enabled.
|
||||
// Must be done before session_start().
|
||||
|
||||
|
||||
123
Zotlabs/Web/SessionRedis.php
Normal file
123
Zotlabs/Web/SessionRedis.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Web;
|
||||
|
||||
|
||||
class SessionRedis implements \SessionHandlerInterface {
|
||||
|
||||
private $redis = null;
|
||||
|
||||
|
||||
function __construct($connection) {
|
||||
|
||||
$this->redis = new \Redis();
|
||||
|
||||
$credentials = parse_url($connection);
|
||||
|
||||
try {
|
||||
if (isset($credentials['path']))
|
||||
$this->redis->connect($credentials['path']);
|
||||
else {
|
||||
|
||||
if (isset($credentials['query']))
|
||||
parse_str($credentials['query'], $vars);
|
||||
else
|
||||
$vars = [];
|
||||
|
||||
$this->redis->connect(
|
||||
(isset($credentials['scheme']) ? $credentials['scheme'] . '://' : '') . $credentials['host'],
|
||||
(isset($credentials['port']) ? $credentials['port'] : 6379),
|
||||
(isset($vars['timeout']) ? $vars['timeout'] : 1),
|
||||
null,
|
||||
0,
|
||||
(isset($vars['read_timeout']) ? $vars['read_timeout'] : 0)
|
||||
);
|
||||
|
||||
if (isset($vars['auth']))
|
||||
$this->redis->auth($vars['auth']);
|
||||
}
|
||||
}
|
||||
catch(\RedisException $ex) {
|
||||
logger('Error connecting to Redis: ' . $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function open($s, $n) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// IMPORTANT: if we read the session and it doesn't exist, create an empty record.
|
||||
// We rely on this due to differing PHP implementation of session_regenerate_id()
|
||||
// some which call read explicitly and some that do not. So we call it explicitly
|
||||
// just after sid regeneration to force a record to exist.
|
||||
|
||||
function read($id) {
|
||||
|
||||
if ($id) {
|
||||
$data = $this->redis->get($id);
|
||||
|
||||
if ($data)
|
||||
return $data;
|
||||
else
|
||||
$this->redis->setEx($id, 300, '');
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
function write($id, $data) {
|
||||
|
||||
// Pretend everything is hunky-dory, even though it isn't.
|
||||
// There probably isn't anything we can do about it in any event.
|
||||
// See: https://stackoverflow.com/a/43636110
|
||||
|
||||
if(! $id || ! $data)
|
||||
return true;
|
||||
|
||||
|
||||
// Unless we authenticate somehow, only keep a session for 5 minutes
|
||||
// The viewer can extend this by performing any web action using the
|
||||
// original cookie, but this allows us to cleanup the hundreds or
|
||||
// thousands of empty sessions left around from web crawlers which are
|
||||
// assigned cookies on each page that they never use.
|
||||
|
||||
$expire = 300;
|
||||
|
||||
if($_SESSION) {
|
||||
if(array_key_exists('remember_me',$_SESSION) && intval($_SESSION['remember_me']))
|
||||
$expire = 60 * 60 * 24 * 365;
|
||||
elseif(local_channel())
|
||||
$expire = 60 * 60 * 24 * 3;
|
||||
elseif(remote_channel())
|
||||
$expire = 60 * 60 * 24 * 1;
|
||||
}
|
||||
|
||||
$this->redis->setEx($id, $expire, $data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function close() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function destroy ($id) {
|
||||
|
||||
$this->redis->del($id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function gc($expire) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,10 +12,14 @@ class Activity_filter {
|
||||
if(! local_channel())
|
||||
return '';
|
||||
|
||||
$cmd = \App::$cmd;
|
||||
$filter_active = false;
|
||||
|
||||
$tabs = [];
|
||||
$filter_active = '';
|
||||
$dm_active = '';
|
||||
$events_active = '';
|
||||
$polls_active = '';
|
||||
$starred_active = '';
|
||||
$conv_active = '';
|
||||
$tabs = [];
|
||||
$cmd = \App::$cmd;
|
||||
|
||||
if(x($_GET,'dm')) {
|
||||
$dm_active = (($_GET['dm'] == 1) ? 'active' : '');
|
||||
@@ -64,6 +68,8 @@ class Activity_filter {
|
||||
);
|
||||
|
||||
if($groups) {
|
||||
$group_active = '';
|
||||
|
||||
foreach($groups as $g) {
|
||||
if(x($_GET,'gid')) {
|
||||
$group_active = (($_GET['gid'] == $g['id']) ? 'active' : '');
|
||||
@@ -95,6 +101,8 @@ class Activity_filter {
|
||||
$channel = App::get_channel();
|
||||
|
||||
if($forums) {
|
||||
$forum_active = '';
|
||||
|
||||
foreach($forums as $f) {
|
||||
if(x($_GET,'pf') && x($_GET,'cid')) {
|
||||
$forum_active = ((x($_GET,'pf') && $_GET['cid'] == $f['abook_id']) ? 'active' : '');
|
||||
@@ -103,10 +111,10 @@ class Activity_filter {
|
||||
$fsub[] = [
|
||||
'label' => $f['xchan_name'],
|
||||
'img' => $f['xchan_photo_s'],
|
||||
'url' => (($f['private_forum']) ? $f['xchan_url'] . '/?f=&zid=' . $channel['xchan_addr'] : z_root() . '/' . $cmd . '/?f=&pf=1&cid=' . $f['abook_id']),
|
||||
'url' => ((isset($f['private_forum'])) ? $f['xchan_url'] . '/?f=&zid=' . $channel['xchan_addr'] : z_root() . '/' . $cmd . '/?f=&pf=1&cid=' . $f['abook_id']),
|
||||
'sel' => $forum_active,
|
||||
'title' => t('Show posts to this forum'),
|
||||
'lock' => (($f['private_forum']) ? 'lock' : '')
|
||||
'lock' => ((isset($f['private_forum'])) ? 'lock' : '')
|
||||
];
|
||||
}
|
||||
|
||||
@@ -160,6 +168,8 @@ class Activity_filter {
|
||||
);
|
||||
|
||||
if($terms) {
|
||||
$file_active = '';
|
||||
|
||||
foreach($terms as $t) {
|
||||
if(x($_GET,'file')) {
|
||||
$file_active = (($_GET['file'] == $t['term']) ? 'active' : '');
|
||||
|
||||
@@ -9,7 +9,7 @@ class Cover_photo {
|
||||
require_once('include/channel.php');
|
||||
$o = '';
|
||||
|
||||
if(\App::$module == 'channel' && $_REQUEST['mid'])
|
||||
if(\App::$module == 'channel' && isset($_REQUEST['mid']))
|
||||
return '';
|
||||
|
||||
$channel_id = 0;
|
||||
|
||||
@@ -175,13 +175,13 @@ class Notifications {
|
||||
];
|
||||
}
|
||||
|
||||
$o = replace_macros(get_markup_template('notifications_widget.tpl'), array(
|
||||
$o = replace_macros(get_markup_template('notifications_widget.tpl'), [
|
||||
'$module' => \App::$module,
|
||||
'$notifications' => $notifications,
|
||||
'$no_notifications' => t('Sorry, you have got no notifications at the moment'),
|
||||
'$loading' => t('Loading'),
|
||||
'$startpage' => $channel['channel_startpage']
|
||||
));
|
||||
'$startpage' => ($channel ? $channel['channel_startpage'] : '')
|
||||
]);
|
||||
|
||||
return $o;
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class Pinned {
|
||||
|
||||
$midb64 = 'b64.' . base64url_encode($item['mid']);
|
||||
|
||||
if(in_array($observer['xchan_hash'], get_pconfig($item['uid'], 'pinned_hide', $midb64, [])))
|
||||
if(isset($observer['xchan_hash']) && in_array($observer['xchan_hash'], get_pconfig($item['uid'], 'pinned_hide', $midb64, [])))
|
||||
continue;
|
||||
|
||||
$author = channelx_by_hash($item['author_xchan']);
|
||||
@@ -67,7 +67,7 @@ class Pinned {
|
||||
$conv_responses['attendno'] = [ 'title' => t('Not attending','title') ];
|
||||
$conv_responses['attendmaybe'] = [ 'title' => t('Might attend','title') ];
|
||||
if($commentable && $observer) {
|
||||
$attend = array( t('I will attend'), t('I will not attend'), t('I might attend'));
|
||||
$attend = [ t('I will attend'), t('I will not attend'), t('I might attend') ];
|
||||
$isevent = true;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ class Pinned {
|
||||
$conv_responses['disagree'] = [ 'title' => t('Disagree','title') ];
|
||||
$conv_responses['abstain'] = [ 'title' => t('Abstain','title') ];
|
||||
if($commentable && $observer) {
|
||||
$conlabels = array( t('I agree'), t('I disagree'), t('I abstain'));
|
||||
$conlabels = [ t('I agree'), t('I disagree'), t('I abstain') ];
|
||||
$canvote = true;
|
||||
}
|
||||
}
|
||||
@@ -93,14 +93,13 @@ class Pinned {
|
||||
// This actually turns out not to be possible in some protocol stacks without opening up hundreds of new issues.
|
||||
// Will allow it only for uri resolvable sources.
|
||||
if(strpos($item['mid'],'http') === 0) {
|
||||
$share = []; //Not yet ready for primetime
|
||||
//$share = array( t('Repeat This'), t('repeat'));
|
||||
$share = []; // Isn't yet ready for primetime
|
||||
//$share = [ t('Repeat This'), t('repeat') ];
|
||||
}
|
||||
$embed = array( t('Share This'), t('share'));
|
||||
$embed = [ t('Share This'), t('share') ];
|
||||
}
|
||||
|
||||
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
|
||||
$is_new = true;
|
||||
|
||||
$is_new = boolval(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0);
|
||||
|
||||
$body = prepare_body($item,true);
|
||||
|
||||
@@ -118,7 +117,7 @@ class Pinned {
|
||||
'isevent' => $isevent,
|
||||
'attend' => $attend,
|
||||
'consensus' => $consensus,
|
||||
'conlabels' => $conlabels,
|
||||
'conlabels' => ($canvote ? $conlabels : []),
|
||||
'canvote' => $canvote,
|
||||
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, ($author['xchan_addr'] ? $author['xchan_addr'] : $author['xchan_url']) ),
|
||||
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $owner['xchan_name'], ($owner['xchan_addr'] ? $owner['xchan_addr'] : $owner['xchan_url']) ),
|
||||
@@ -135,7 +134,6 @@ class Pinned {
|
||||
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
|
||||
'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r') ) : ''),
|
||||
'expiretime' => ($item['expires'] > NULL_DATE ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r') ) : ''),
|
||||
'lock' => $lock,
|
||||
'verified' => $verified,
|
||||
'forged' => $forged,
|
||||
'location' => $location,
|
||||
@@ -150,12 +148,12 @@ class Pinned {
|
||||
'event' => $body['event'],
|
||||
'has_tags' => (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false),
|
||||
// Item toolbar buttons
|
||||
'share' => $share,
|
||||
'embed' => $embed,
|
||||
'share' => (isset($share) && count($share) ? $share : false),
|
||||
'embed' => (isset($embed) && count($embed) ? $embed : false),
|
||||
'plink' => get_plink($item),
|
||||
'pinned' => t('Pinned post'),
|
||||
'pinme' => (($observer['xchan_hash'] == $owner['xchan_hash']) ? t('Unpin from the top') : ''),
|
||||
'hide' => (! $is_new && $observer && ($observer['xchan_hash'] != $owner['xchan_hash']) ? t("Don't show") : ''),
|
||||
'pinme' => (isset($observer['xchan_hash']) && $observer['xchan_hash'] == $owner['xchan_hash'] ? t('Unpin from the top') : ''),
|
||||
'hide' => (! $is_new && isset($observer['xchan_hash']) && $observer['xchan_hash'] != $owner['xchan_hash'] ? t("Don't show") : ''),
|
||||
// end toolbar buttons
|
||||
'modal_dismiss' => t('Close'),
|
||||
'responses' => $conv_responses
|
||||
|
||||
18
boot.php
18
boot.php
@@ -52,10 +52,10 @@ require_once('include/attach.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
define ( 'PLATFORM_NAME', 'hubzilla' );
|
||||
define ( 'STD_VERSION', '5.4.2' );
|
||||
define ( 'STD_VERSION', '5.6' );
|
||||
define ( 'ZOT_REVISION', '6.0' );
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1243 );
|
||||
define ( 'DB_UPDATE_VERSION', 1245 );
|
||||
|
||||
define ( 'PROJECT_BASE', __DIR__ );
|
||||
|
||||
@@ -2316,13 +2316,14 @@ function construct_page() {
|
||||
$navbar = get_pconfig($uid,'system','navbar',$navbar);
|
||||
}
|
||||
|
||||
if($comanche && App::$layout['navbar']) {
|
||||
if($comanche && isset(App::$layout['navbar'])) {
|
||||
$navbar = App::$layout['navbar'];
|
||||
}
|
||||
|
||||
if (App::$module == 'setup') {
|
||||
$installing = true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
nav($navbar);
|
||||
}
|
||||
|
||||
@@ -2428,7 +2429,6 @@ function construct_page() {
|
||||
'style-src' => [ "'self'", "'unsafe-inline'" ],
|
||||
'frame-src' => [ "'self'" ]
|
||||
];
|
||||
|
||||
call_hooks('content_security_policy',$cspsettings);
|
||||
|
||||
// Legitimate CSP directives (cxref: https://content-security-policy.com/)
|
||||
@@ -2460,6 +2460,14 @@ function construct_page() {
|
||||
header("X-Content-Type-Options: nosniff");
|
||||
}
|
||||
|
||||
if (isset(App::$config['system']['perm_policy_header']) && App::$config['system']['perm_policy_header']) {
|
||||
header("Permissions-Policy: " . App::$config['system']['perm_policy_header']);
|
||||
}
|
||||
else {
|
||||
// opt-out this site from federated browser surveillance
|
||||
header("Permissions-Policy: interest-cohort=()");
|
||||
}
|
||||
|
||||
if(isset(App::$config['system']['public_key_pins'])) {
|
||||
header("Public-Key-Pins: " . App::$config['system']['public_key_pins']);
|
||||
}
|
||||
|
||||
112
doc/admin/zarlog_msgs.md
Normal file
112
doc/admin/zarlog_msgs.md
Normal file
@@ -0,0 +1,112 @@
|
||||
~~~
|
||||
L regate ZAR1131E dId2 mistaken
|
||||
L ZAR1132E Identity unknown
|
||||
ZAR1133A Sorry for any inconvience. Thank you for your response.
|
||||
L ZAR1134S email verfication denied {did2}
|
||||
L ZAR1135E not awaited url parameter received
|
||||
|
||||
L regate ZAR1230S Unexpected registration verification request for
|
||||
L ZAR1231E dId2 mistaken
|
||||
L ZAR1232E Identity unknown
|
||||
L ZAR1234W Request not inside time frame
|
||||
L ZAR1235E Token verification failed
|
||||
ZAR1236I Verify successfull
|
||||
L ZAR1236E Verify failed
|
||||
L ZAR1237D unexpected
|
||||
(reason may be caused by new account flags implemented still not known)
|
||||
ZAR1238I Email resent
|
||||
ZAR1238E Resent failed
|
||||
L ZAR1239I Account successfull created
|
||||
L ZAR1239E Account creation error
|
||||
|
||||
register ZAR0130E Registration on this hub is disabled.
|
||||
ZAR0131I Registration on this hub is by approval only.
|
||||
Register at another affiliated hub in case when prefered
|
||||
ZAR0132I Registration on this hub is by invitation only.
|
||||
Register at another affiliated hub
|
||||
ZAR0133I If the registation was already submitted with your data once ago,
|
||||
enter your identity (like email) here and submit
|
||||
ZAR0134I I have an invite code
|
||||
ZAR0135I This site requires verification. After completing this form,
|
||||
please check the notice or your email for further instructions.
|
||||
ZAR0136I Your email address (or leave blank to register without email)
|
||||
|
||||
L register ZAR0230S Unexpected registration request
|
||||
ZAR0231E Email address mistake
|
||||
ZAR0231E Passwords do not match.
|
||||
ZAR0231E Please indicate acceptance of the Terms of Service. Registration failed.
|
||||
ZAR0232E Invitations are not available
|
||||
L ZAR0233E Registration on this hub is by invitation only
|
||||
L ZAR0234S Invitation code failed
|
||||
L ZAR0235S Invitation email failed
|
||||
ZAR0236E Invitation not in time or too late
|
||||
ZAR0237I Invitation code succesfully applied
|
||||
L ZAR0238E Email address already in use
|
||||
L ZAR0239D Error creating dId A
|
||||
ZAR0239I Your didital id is {did2} and your pin for is {pin}
|
||||
Keep these infos and your entered password safe
|
||||
Valid from ... nd expire ...
|
||||
L ZAR0239S Exceeding same ip register request of
|
||||
|
||||
ui:admin:site
|
||||
ZAR0810C Register text
|
||||
Will be displayed prominently on the registration page.
|
||||
ZAR0820C register_policy
|
||||
Does this site allow new member registration?
|
||||
ZAR0830C Registration office on duty
|
||||
The weekdays and hours the register office is open for registrations
|
||||
ZAR0831I Testmode duties
|
||||
(interactive)
|
||||
ZAR0840C Account registrations max per day
|
||||
How many registration requests the site accepts during one day. Unlimited if zero or no value.
|
||||
ZAR0850C Account registrations from same ip
|
||||
How many pending registration requests the site accepts from a same ip address.
|
||||
ZAR0860C Account registration delay
|
||||
How long a registration request has to wait before validation can perform
|
||||
ZAR0862C Account registration expiration
|
||||
How long a registration to confirm remains valid. Not expire if zero or no value
|
||||
ZAR0870C Auto channel create
|
||||
Auto create a channel when register a new account. When On, the register form will show
|
||||
additional fields for the channel-name and the nickname.
|
||||
ZAR0880C Invitation only
|
||||
Only allow new member registrations with an invitation code.
|
||||
Above register policy must be set to Yes.
|
||||
ZAR0881C Invitation also
|
||||
Also allow new member registrations with an invitation code.
|
||||
Above register policy must be set to Yes.
|
||||
ZAR0890C Verify Email Addresses
|
||||
Check to verify email addresses used in account registration (recommended).
|
||||
|
||||
invite ZAI0100E All users invitation limit exceeded
|
||||
ZAI0101E Permission denied.
|
||||
ZAI0102E Invite App (Not Installed)
|
||||
ZAI0103E Invites not proposed by configuration. Contact the site admin
|
||||
ZAI0104E Invites by users not enabled
|
||||
ZAI0105W You have no more invitations available
|
||||
ZAI0106I Invitations I am using
|
||||
ZAI0107I Invitations we are using
|
||||
ZAI0109E Not on xchan
|
||||
ZAI0110I § Note, the email(s) sent will be recorded in the system logs
|
||||
(see ZAI0208I @ L)
|
||||
ZAI0111I Enter email addresses, one per line
|
||||
ZAI0112I Your message
|
||||
Here you may enter personal notes to the recipient(s)
|
||||
ZAI0113I Invite template
|
||||
ZAI0114I Note, the invitation code is valid up to ...
|
||||
|
||||
invite ZAI0201E Permission denied.
|
||||
ZAI0202E Invite App (Not Installed)
|
||||
ZAI0203E Not a valid email address
|
||||
ZAI0204E Not a real email address
|
||||
ZAI0205E Not allowed email address
|
||||
ZAI0206E mail address already in use
|
||||
ZAI0207I Note, the invitation code is valid up to
|
||||
ZAI0208E Message delivery failed.
|
||||
ZAI0208I Message delivery success.
|
||||
L ZAI0208I to {email} Message delivery success. ({account#}, {channel#}, from:{email}})
|
||||
ZAI0209I Accepted email address
|
||||
ZAI0210E Too many recipients for one invitation (max n)
|
||||
ZAI0211E No recipients for this invitation
|
||||
ZAI0212I n mail(s) sent, n mail error(s)
|
||||
ZAI0213E Register is closed
|
||||
~~~
|
||||
12
doc/context/de/register/help.html
Normal file
12
doc/context/de/register/help.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Allgemein</dt>
|
||||
<dd>Auf dieser Seite können sich Besucher registrieren, um mit einer Anmeldungskennung Zugang zum Portal zu erhalten. Angemeldeten Benutzern sehen nicht nur die öffentlichen Inhalte, sondern können selber Inhalte veröffentlichen und Soziale Netzwerk Kommunikationen durchführen, und sehr viel mehr.</dd>
|
||||
<dt>Arten der Registrierung</dt>
|
||||
<dd>Eine Registrierung ist mit einer eMail Adresse möglich, oder auch anonym (dann das eMail Feld nicht ausfüllen). Vielleicht haben Sie auch einen Einladungscode erhalten, der dann mit der eMail Adresse angegeben werden kann. Der Link oberhalb des Feldes eMail ermöglich die Eingabe des Einladungscodes.</dd>
|
||||
<dt>Ablauf der Registrierung</dt>
|
||||
<dd>Für Anmeldungen nach einer erfolgreichen Registrierung ist ein eigenes Kennwort festzulegen. Es ist sicherheitshalber zweimal mit identischen Werten einzugeben, weil es nicht angezeigt wird. Das Kennwort ist geheim zu halten und nur für den eigenen Gebrauch bestimmt. Anonym registrierte Benutzer erhalten eine automatisch zugewiesene Kennung, und sollten das eigene Kennwort nicht vergessen, weil es im Gegensatz zur eMail Registrierung zunächst keine Rücksetzfunktion gibt. Je nach Konfiguration der Hub-Instanz kann eine Bestätigungsfunktion erforderlich sein. Benutzer der eMail Registrierung erhalten eine entsprechende Nachricht. Bei anonymen Registrierungen wird ein weiterer Dialog angezeigt, der die Zugangskennung und eine Pin zeigt. Jene Dialogseite sollte unbedingt sicher und langfristig aufbewahrt werden (z.B. durch Ausdruck, Screenshot, Foto), weil die Daten zu einem späten Zeitpunkt noch einmal zu bestätigen sind.</dd>
|
||||
<dt>Die Digitale Identität</dt>
|
||||
<dd>Je nach Konfiguration der Hub-Instanz kann bereits bei der Registrierung (alternativ auch bei der ersten Anmeldung) ein anzeigbarer Name und ein Spitzname ("nickname") eingegeben werden. Der Nickname hat eine sehr weitreichende Bedeutung und läßt sich nachträglich nicht mehr ändern. Es handelt sich dabei um eine eindeutige Digitale Identität (DID), die mit allen eigenen Aktivitäten verknüft ist, sein wird, und bleibt. Diese DID eignet sich nicht nur zur Anmeldung in dieser Hub-Instanz, sondern auch in allen verbundenen Instanzen des Federalen Netzwerkes. Im Sprachgebrauch der Federalen Netze ist diese digitale Identität ein "Kanal". Das ist vergleichbar etwa mit einer Rufnummer im Telefonnetz. Die DID hat das Format kanal@instanz.tld = nickname@instanz.tld und ist, wie gesagt, nachträglich nicht mehr änderbar. Obwohl sich das Format wie eine eMail Adresse darstellt, handelt es sich nicht um eine solche.</dd>
|
||||
<dt>Bevor die Registrierung begonnen wird ...</dt>
|
||||
<dd>sollte (oben rechts im Hamburger Menü <span class="fa fa-fw fa-bars"> </span>) die bevorzugte Sprache (Englisch, Spanisch, Deutsch z.B.) gewählt werden. Die aktuelle Sprache wird in den Folgeschritten und auch bei und nach der Anmeldung verwendet. Das läßt sich aber jederzeit und je nach Bedarf ändern. Auch sei darauf hingewiesen, dass diese Hub-Instanz nicht die einzige ist. Eine Übersicht über andere Hub-Instanzen ist <a href="./pubsites"> hier </a> zu finden.</dd>
|
||||
</dl>
|
||||
12
doc/context/en/register/help.html
Normal file
12
doc/context/en/register/help.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>General</dt>
|
||||
<dd>On this page visitors can register to get access to the portal with a login ID. Logged in users not only see the public content, but can publish content themselves and perform social network communications, and much more.</dd>
|
||||
<dt>Modes of registration</dt>
|
||||
<dd>Registration is possible with an eMail address, or anonymously (then do not fill in the eMail field). You may also have received an invitation code, which can then be entered with the eMail address. The link above the eMail field allows you to enter the invitation code.</dd>
|
||||
<dt>Registration procedure</dt>
|
||||
<dd>For logins after a successful registration, a separate password must be set. To be on the safe side, enter it twice with identical values, because it will not be displayed. The password is to be kept secret and is only intended for the user's own use. Anonymously registered users receive an automatically assigned ID, and should not forget their own password because, unlike eMail registration, there is initially no reset function. Depending on the configuration of the hub instance, a confirmation function may be required. Users of the eMail registration will receive a corresponding message. For anonymous registrations, another dialog will be displayed showing the access ID and a pin. This dialog page should be stored securely and for a long time (e.g. by printout, screenshot, photo), because the data must be confirmed again at a later point in time.</dd>
|
||||
<dt>The Digital Identity</dt>
|
||||
<dd>Depending on the configuration of the hub instance, a displayable name and a nickname can already be entered during registration (alternatively also during the first login). The nickname has a very extensive meaning and cannot be changed later. It is a unique Digital Identity (DID) that is, will be, and remains linked to all of one's activities. This DID is not only suitable for logging into this hub instance, but also into all connected instances of the federal network. In federal network parlance, this digital identity is a "channel". This is comparable to a telephone number in the telephone network. The DID has the format channel@instance.tld = nickname@instance.tld and, as mentioned, cannot be changed afterwards. Although the format looks like an eMail address, it is not.</dd>
|
||||
<dt>Before starting the registration ...</dt>
|
||||
<dd>... the preferred language (English, Spanish, German, for example) should be selected (top right in the hamburger menu <span class="fa fa-fw fa-bars"> </span>). The current language is used in the subsequent steps and also during and after login. However, this can be changed at any time and as needed. It should also be noted that this Hub instance is not the only one. An overview of other Hub instances can be found <a href="./pubsites"> here </a>.</dd>
|
||||
</dl>
|
||||
@@ -2,6 +2,6 @@
|
||||
<dt>Ogólne</dt>
|
||||
<dd>
|
||||
Statystyki kolejki pokazują, ile postów znajduje się w kolejce do dostarczenia
|
||||
do innych hubów. Priorytet jest powiązany z liczbą nieudanych prób dostawy.
|
||||
do innych węzłów. Priorytet jest powiązany z liczbą nieudanych prób dostawy.
|
||||
</dd>
|
||||
</dl>
|
||||
@@ -22,8 +22,8 @@
|
||||
<li>
|
||||
<b>Kategorie</b>: Jeśli na swoim kanale masz włączoną
|
||||
<a href="/settings/features"> funkcjonalność kategorii postów </a>,
|
||||
możesz dodawać kategorie do karty. Te kategorie zapełniają listę
|
||||
<b>Kategorie</b> na lewym panelu i umożliwiają filtrowanie
|
||||
możesz dodawać kategorie do karty. Kategorie te zawarte są na liście
|
||||
<b>Kategorie</b>, na lewym panelu i umożliwiają filtrowanie
|
||||
kolekcji kart.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
<dd>
|
||||
Wpisz wiadomość w polu wiadomości i naciśnij "Prześlij". Możesz ustawić status,
|
||||
wybierając przycisk menu pokoju rozmów sieciowych obok przycisku "Wyślij".
|
||||
Inne osoby "w pokoju"" są widoczne w panelu bocznym w panelu „Członkowie czatu”.
|
||||
Inne osoby "w pokoju" są widoczne w panelu bocznym w panelu "Członkowie czatu".
|
||||
</dd>
|
||||
</dl>
|
||||
@@ -1,7 +1,7 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Ogólne</dt>
|
||||
<dd>
|
||||
Ta strona wyświetla pliki "w chmurze" kanału. To co widi przeglądajacy zależy
|
||||
Ta strona wyświetla pliki "w chmurze" kanału. To co widzi przeglądajacy zależy
|
||||
od jego indywidualnych uprawnień do plików, które ustawia właściciel kanału.
|
||||
Jeśli masz uprawnienia do tworzenia i przesyłania plików, zobaczysz przyciski
|
||||
kontrolne nad listą plików.
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
title="Kliknij, aby podświetlić element...">Grupy prywatności</a></dt>
|
||||
<dd>
|
||||
Każde połączenie może być przypisane do jednej lub więcej grup prywatności
|
||||
w celu grupowania kolekcji znajomych z dostępem do określonych postów,
|
||||
w celu grupowania kolekcji znajomych z dostępem do określonych wpisów,
|
||||
multimediów i innych treści. Możesz dodać je tutaj do istniejącej grupy
|
||||
prywatności lub utworzyć nową grupę prywatności. Po dodaniu ich do istniejącej
|
||||
grupy akcja jest natychmiastowa i nie musisz przesyłać formularza.
|
||||
@@ -37,7 +37,7 @@
|
||||
<dt>Ustawienia specyficznych funkcji</dt>
|
||||
<dd>
|
||||
Szereg indywidualnych ustawień jest kontrolowanych za pomocą dodatkowych
|
||||
funkcji, które mogą, ale nie muszą być aktywowane na Twoim hubie lub na Twoim
|
||||
funkcji, które mogą, ale nie muszą być aktywowane na Twoim węźle lub na Twoim
|
||||
kanale. Kilka opcjonalnych funkcji ma ustawienia dla każdego połączenia,
|
||||
które można ustawić na tej stronie za pomocą dodatkowych zakładek formularza.
|
||||
</dd>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</dd>
|
||||
<dt>Widok łączony</dt>
|
||||
<dd>
|
||||
Wybór opcji <b>Widok łączony</b> spowoduje wyświetlanie całych rozmów w ciągłym
|
||||
Wybór opcji <b>Widok łączony</b> spowoduje wyświetlanie wszystkich rozmów w ciągłym
|
||||
wątku. Dostępne rozmowy są wyświetlane poniżej menu w panelu bocznym.
|
||||
</dd>
|
||||
<dt>Skrzynka odbiorcza/nadawcza</dt>
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Ogólne</dt>
|
||||
<dd>
|
||||
Strona strumienia sieciowego wyświetla strumień postów i rozmów, zwykle
|
||||
Strona strumienia sieciowego wyświetla strumień wpisów i rozmów, zwykle
|
||||
uporządkowanych według ostatnio zaktualizowanych. Jest to strona wysoce konfigurowalna.
|
||||
</dd>
|
||||
<dt><a href='#' onclick='contextualHelpFocus("#profile-jot-wrapper", 0);
|
||||
return false;' title="Kliknij, aby podświetlić element...">Tworzenie posta</a></dt>
|
||||
return false;' title="Kliknij, aby podświetlić element...">Tworzenie wpisu</a></dt>
|
||||
<dd>
|
||||
U góry strony znajduje się pole tekstowe z napisem "Udostępnij". Kliknięcie
|
||||
tego pola otwiera nowy edytor postówów. Edytor postów można dostosowywać, ale
|
||||
podstawowy edytor udostępnia pola dla treści posta i opcjonalnego <b>tytułu</b>.
|
||||
tego pola otwiera nowy edytor wpisów. Edytor wpisów można dostosowywać, ale
|
||||
podstawowy edytor udostępnia pola dla treści wpisu i opcjonalnego <b>tytułu</b>.
|
||||
Przyciski poniżej obszaru tekstowego po lewej stronie zapewniają skróty do
|
||||
formatowania tekstu i wstawiania linków, obrazów i innych danych do posta.
|
||||
Przyciski po prawej stronie zapewniają podgląd posta, ustawienia uprawnień do
|
||||
publikowania oraz przycisk <b>Prześlij</b> do wysłania posta.
|
||||
formatowania tekstu i wstawiania linków, obrazów i innych danych do wpisu.
|
||||
Przyciski po prawej stronie zapewniają podgląd wpisu, ustawienia uprawnień do
|
||||
publikowania oraz przycisk <b>Prześlij</b> do wysłania wpisu.
|
||||
</dd>
|
||||
<dt><a href='#' onclick='contextualHelpFocus("#group-sidebar", 1);
|
||||
return false;' title="Kliknij, aby podświetlić element...">Grupy prywatności</a></dt>
|
||||
<dd>
|
||||
Utworzone grupy prywatności są wyświetlane w panelu bocznym. Wybranie ich
|
||||
powoduje filtrowanie postów do tych utworzonych przez kanały w wybranej grupie.
|
||||
powoduje filtrowanie wpisów do tych utworzonych przez kanały w wybranej grupie.
|
||||
</dd>
|
||||
<dt><a href='#' onclick='$("#dbtn-acl").click(); return false;'
|
||||
title="Kliknij, aby podświetlić element...">Uprawnienia do posta</a></dt>
|
||||
title="Kliknij, aby podświetlić element...">Uprawnienia do wpisu</a></dt>
|
||||
<dd>
|
||||
Lista kontroli dostępu (ACL) służy do określania, kto może zobaczyć Twój nowy
|
||||
post. Naciśnięcie przycisku ACL obok przycisku Prześlij spowoduje wyświetlenie
|
||||
wpis. Naciśnięcie przycisku ACL obok przycisku Prześlij spowoduje wyświetlenie
|
||||
okna dialogowego, w którym możesz wybrać kanały albo grupy prywatności, które
|
||||
będą widzieć post. Możesz także wybrać, komu wyraźnie odmówiono dostęp.
|
||||
będą widzieć wpis. Możesz także wybrać, komu wyraźnie odmówiono dostęp.
|
||||
Załóżmy na przykład, że planujesz przyjęcie niespodziankę dla znajomego.
|
||||
Możesz wysłać zaproszenie do wszystkich w swojej grupie <b>Znajomi</b>
|
||||
<i>oprócz</i> znajomego, którego zaskakujesz. W tym przypadku "pokazujesz"
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
się z osobami w życiu codziennym. Lecz być może jesteś zapalonym
|
||||
czytelnikiem książek a wielu ludzi się tym nudzi. Otwierasz więc
|
||||
<i>drugi kanał</i> dla miłośników książek, gdzie wszyscy mogą rozmawiać
|
||||
o książkach tyle, ile zechcą. Oczywiście jest to nowy strumień postów,
|
||||
o książkach tyle, ile zechcą. Oczywiście jest to nowy strumień wpisów,
|
||||
z nowym profilem (... lub nowymi profilami) i zupełnie z innymi
|
||||
kontaktami. Niektóre połączenia mogą istnieć w obu kanałach, ale będą
|
||||
takie, które będą występować wyłącznie w jednym z nich. Ty po prostu
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
się z osobami w życiu codziennym. Lecz być może jesteś zapalonym
|
||||
czytelnikiem książek a wielu ludzi się tym nudzi. Otwierasz więc
|
||||
<i>drugi kanał</i> dla miłośników książek, gdzie wszyscy mogą rozmawiać
|
||||
o książkach tyle, ile zechcą. Oczywiście jest to nowy strumień postów,
|
||||
o książkach tyle, ile zechcą. Oczywiście jest to nowy strumień wpisów,
|
||||
z nowym profilem (... lub nowymi profilami) i zupełnie z innymi
|
||||
kontaktami. Niektóre połączenia mogą istnieć w obu kanałach, ale będą
|
||||
takie, które będą występować wyłącznie w jednym z nich. Ty po prostu
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
się z osobami w życiu codziennym. Lecz być może jesteś zapalonym
|
||||
czytelnikiem książek a wielu ludzi się tym nudzi. Otwierasz więc
|
||||
<i>drugi kanał</i> dla miłośników książek, gdzie wszyscy mogą rozmawiać
|
||||
o książkach tyle, ile zechcą. Oczywiście jest to nowy strumień postów,
|
||||
o książkach tyle, ile zechcą. Oczywiście jest to nowy strumień wpisów,
|
||||
z nowym profilem (... lub nowymi profilami) i zupełnie z innymi
|
||||
kontaktami. Niektóre połączenia mogą istnieć w obu kanałach, ale będą
|
||||
takie, które będą występować wyłącznie w jednym z nich. Ty po prostu
|
||||
|
||||
@@ -1,35 +1,50 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Ogólne</dt>
|
||||
<dt>Informacje ogólne</dt>
|
||||
<dd>
|
||||
Ta strona umożliwia skonfigurowanie ustawień dla wielu dodatkowych funkcji Hubzilli.
|
||||
Ta strona umożliwia skonfigurowanie ustawień dla wielu dodatkowych funkcji Hubzilli, które możesz włączyć na swoim koncie.
|
||||
</dd>
|
||||
<dt><a href='#' onclick='$("#general-settings-title h3 a").click();
|
||||
setTimeout((function() {contextualHelpFocus("#general-settings-title", 0)}), 1000);
|
||||
return false;' title="Klikniaj, aby podświetlić element...">Główne cechy</a></dt>
|
||||
<dt><a href="/help/pl/feature/additional/overview#calendar_settings">Kalendarz</a></dt>
|
||||
<dd>
|
||||
Ogólne ustawienia funkcji zawierają opcje związane z Twoim kanałem, takie jak
|
||||
hosting strony internetowej i wiki.
|
||||
Są to dodatkowe opcje, które możesz włączyć dla wszystkich swoich kalendarzy.
|
||||
Można to zmienić indywidualnie w każdym kalendarzu.<br />
|
||||
</dd>
|
||||
<dt><a href='#' onclick='$("#composition-settings-title h3 a").click();
|
||||
setTimeout((function() {contextualHelpFocus("#composition-settings-title", 0)}), 1000);
|
||||
return false;' title="Klikniaj, aby podświetlić element...">Funkcje kompozycji postów</a></dt>
|
||||
<dt><a href="/help/pl/feature/additional/overview#channel_main_page_settings">Strona główna kanału</a></dt>
|
||||
<dd>
|
||||
Funkcje kompozycji postów zapewniają dodatkowe opcje i możliwości podczas
|
||||
tworzenia nowych postów.
|
||||
Kilka dodatkowych możliwości związanych ze stroną główną kanału.
|
||||
</dd>
|
||||
<dt><a href='#' onclick='$("#net_module-settings-title h3 a").click();
|
||||
setTimeout((function() {contextualHelpFocus("#net_module-settings-title", 0)}), 1000);
|
||||
return false;' title="Klikniaj, aby podświetlić element...">Sieć i fitrowanie strumienia</a></dt>
|
||||
<dt><a href="/help/pl/feature/additional/overview#connections_settings">Połączenia</a></dt>
|
||||
<dd>
|
||||
Te ustawienia modyfikują funkcje związane z filtrowaniem i kontrolowaniem widoku
|
||||
przychodzących postów.
|
||||
Obecnie jest tu tylko ustawienie opcji umożliwiającej filtrowanie strumienia wg
|
||||
słów kluczowych lub treści (fraz).
|
||||
</dd>
|
||||
<dt><a href='#' onclick='$("#tools-settings-title h3 a").click();
|
||||
setTimeout((function() {contextualHelpFocus("#tools-settings-title", 0)}), 1000);
|
||||
return false;' title="Klikniaj, aby podświetlić element...">Narzędzia postów i komentarzy</a></dt>
|
||||
<dt><a href="/help/pl/feature/additional/overview#conversation-settings">Rozmowa</a></dt>
|
||||
<dd>
|
||||
Ustawienia te zapewniają dodatkowe narzędzia do kategoryzowania postów
|
||||
i umożliwiają dodatkowe metody komentowania, takie jak emoji lub tagowanie
|
||||
społecznościowe.
|
||||
Kilka dodatkowych opcji rozszerzających obsługę rozmów i dyskusji.
|
||||
</dd>
|
||||
<dt><a href="/help/pl/feature/additional/overview#directoty_settings">Katalog</a></dt>
|
||||
<dd>
|
||||
Dostępna tu opcja zaawansowanego przeszukiawania katalogu może być bardzo użyteczna
|
||||
dla osób chcących dotrzeć do konkretnych informacji publikowanych w sieci Hubzilla.
|
||||
</dd>
|
||||
<dt><a href="/help/pl/feature/additional/overview#manage_settings">Zarządzanie</a></dt>
|
||||
<dd>
|
||||
Dostępna tu opcja włącza funkcję zmiany kanału bezpośrednio z rozwijanego menu nawigacji.
|
||||
</dd>
|
||||
<dt><a href="/help/pl/feature/additional/overview#network-settings">Sieć</a></dt>
|
||||
<dd>
|
||||
Znajduje się tu szereg opcji włączających funkcje związane z siecią i strumieniem
|
||||
sieciowym. Przede wszystkim dostępnych jest tu kilka dodatkowych filtrów i inne
|
||||
użyteczne funkcje. Szczegóły można znaleźć dokumentacji.
|
||||
</dd>
|
||||
<dt><a href="/help/pl/feature/additional/overview#photos_settings">Zdjęcia</a></dt>
|
||||
<dd>
|
||||
Tutaj można włączyć funkcję wyświetlania na mapie lokalizacji zdjęcia, jeśli
|
||||
polik zdjęcia zawiera potrzebne metadane.
|
||||
</dd>
|
||||
<dt><a href="/help/pl/feature/additional/overview#profiles_settings">Profile</a></dt>
|
||||
<dd>
|
||||
W tej sekcji zawarte są opcje włączające dodatkowe funkcje dotyczące profilu.
|
||||
Jeśli chcesz i możesz zakładać na swoim koncie wiele profili (i tożsamości),
|
||||
włącz tu opcję "wiele profili".
|
||||
</dd>
|
||||
</dl>
|
||||
@@ -1,14 +1,14 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt><a href="/help/member/member_guide#Guest_Access_Tokens">Tokeny dostępu gościa</a></dt>
|
||||
<dt><a href="/help/member/member_guide#Tokeny_dost_pu_go_cia">Tokeny dostępu gościa</a></dt>
|
||||
<dd>
|
||||
Aby ułatwić udostępnianie prywatnych zasobów osobom niebędącym członkami
|
||||
lub członkami sfederyzowanych węzłów (hubów) i zapewnić zabezpieczone
|
||||
lub członkami sfederyzowanych węzłów (węzłów) i zapewnić zabezpieczone
|
||||
wykrywaniem danych identyfikacyjnych, Hubzilla zawiera mechanizm tworzenia
|
||||
i zarządzania tymczasowymi ("jednorazowymi") loginami, zwanymi "tokenami
|
||||
dostępu Zot”. Tokeny te, będące swojego rodzaju danymi uwierzytelniającymi,
|
||||
mogą być używane do uwierzytelniania w serwisie Hubzilla wyłącznie w celu
|
||||
uzyskania dostępu do uprzywilejowanych lub kontrolowanych zasobów (pliki,
|
||||
zdjęcia, posty, strony internetowe, pokoje rozmów itp.).
|
||||
zdjęcia, wpisy, strony internetowe, pokoje rozmów itp.).
|
||||
</dd>
|
||||
<dt>Utworzenie tokenu</dt>
|
||||
<dd>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Return to the [zrl=[baseurl]/help/addons]Dokumentacja dodatków[/zrl]
|
||||
Return to the [zrl=[baseurl]/help/main]Główna dokumentacja[/zrl]
|
||||
Powróć do [zrl=[baseurl]/help/addons]dokumentacji dodatków[/zrl]
|
||||
Powróć do [zrl=[baseurl]/help/main]głównej strony dokumentacji[/zrl]
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Return to the [zrl=[baseurl]/help/cloud]Dokumentacja chmury[/zrl]
|
||||
Return to the [zrl=[baseurl]/help/main]Główna strona dokumentacji[/zrl]
|
||||
Powróć do [zrl=[baseurl]/help/cloud]dokumentacji chmury[/zrl]
|
||||
Powróć do [zrl=[baseurl]/help/main]głównej strony dokumentacji[/zrl]
|
||||
|
||||
@@ -1,107 +1,173 @@
|
||||
Dodatkowe możliwości
|
||||
Opcje konfiguracyjne
|
||||
====================
|
||||
|
||||
Domyślny interfejs $Projectname został zaprojektowany tak, aby był dobrze uporządkowany. Istnieje ogromna liczba dodatkowych funkcji (niektóre są bardzo przydatne), które można włączyć i jak najlepiej wykorzystać. Można je znaleźć pod klikając link [Dodatkowe funkcje](settings/features) na stronie [Ustawienia](settings).
|
||||
Po zainstalowaniu, serwis $Projectname jest wstępnie konfigurowany z domyślnymi wartościami. Z reguły, wymaga to odpowiedniego dostrojemia tak, aby konfiguracja odpowiadała zakładanym funkcjom serwisu.
|
||||
|
||||
**Wygaśnięcie treści**
|
||||
Ustawianie dodatkowych możliwości poprzez interfejs graficzny
|
||||
-------------------------------------------------------------
|
||||
|
||||
Usuwanie postów, komentarzy albo prywatnych wiadomości w określonym terminie. Do edytora postów zostaje dodany dodatkowy przycisk, za pomoca któreg można ustawić termin wygaśnięcia publikacji. Zwykle data jest wyświetlana w formacie „rrrr-mm-dd gg: mm”, ale w języku angielskim ma się nieco większą swobodę i można używać większości rozpoznawalnych odniesień do dat, takich jak "next Thursday" czy "+1 day". W określonym terminie (podanym lub zajmującym około dziesięciu minut, w zależności od częstotliwości sprawdzania zdalnego systemu) element jest usuwany.
|
||||
Domyślny interfejs $Projectname został zaprojektowany tak, aby był dobrze uporządkowany. Istnieje spora liczba dodatkowych funkcjonalności (o różnej przydatności), które można włączyć i później wykorzystywać. Można je znaleźć klikając link [Dodatkowe możliwości](admin/features) na stronie [Administracja](/admin). Są one tam prezentowane w kilku grupach.
|
||||
|
||||
#### Kalendarz
|
||||
|
||||
**Rozpocznij tydzień kalendarzowy w poniedziałek**
|
||||
|
||||
Daje możliwość skonfigurowania kalendarza tak, aby tydzień kalendarzowy zaczynał się w poniedziałek.
|
||||
|
||||
**Wybór strefy czasowej wydarzenia**
|
||||
|
||||
Daje możliwość konfigurowania strefy czasowej wydarzenia w kalendarzu.
|
||||
|
||||
#### Strona główna kanału
|
||||
|
||||
**Wyszukaj po dacie**
|
||||
|
||||
Daje możliwość wyboru wpisów według zakresów dat.
|
||||
|
||||
**Chmura tagów**
|
||||
|
||||
Udostępnienie osobistej chmury tagów na stronie swojego kanału.
|
||||
|
||||
**Użyj trybu blog/lista**
|
||||
|
||||
Pozwoduje, że komentarze są wyświetlane osobno.
|
||||
|
||||
#### Połączenia
|
||||
|
||||
**Filtrowanie połączeń**
|
||||
|
||||
Umożliwia filtrowanie przychodzących wpisów z połączeń, na podstawie słów kluczowych lub fragnentów treści.
|
||||
|
||||
#### Rozmowa
|
||||
|
||||
**Reakcje emoji**
|
||||
|
||||
Dodaje możliwość wstawiania reakcji emoji we wpisach.
|
||||
|
||||
**Nielubienie wpisu**
|
||||
|
||||
Możliwość oznaczania wpisów i komentarzy jako nielubiane.
|
||||
|
||||
**Wyróżnienie wpisu**
|
||||
|
||||
Możliwość oznaczania wyróżnionych wpisów wskaźnikiem gwiazdki.
|
||||
|
||||
**Odpowiadanie na komentarze**
|
||||
|
||||
Możliwość udzielenia odpowiedzi na wybrany komentarz.
|
||||
|
||||
#### Katalog
|
||||
|
||||
**Zaawansowane przeszukiwanie katalogu**
|
||||
|
||||
Umożliwia tworzenie złożonych zapytań wyszukiwania w katalogu.
|
||||
|
||||
#### Edytor
|
||||
|
||||
**Kategorie wpisów**
|
||||
|
||||
Możliwość dodawania kategorii do swoich wpisów.
|
||||
|
||||
**Duże zdjęcia**
|
||||
|
||||
Możliwość zamieszczania dużych miniatur zdjęć (1024px) we wpisach. Jeśli nie jest to włączone, można używać tylko małych miniatur (640 px).
|
||||
|
||||
**Jeszcze więcej szyfrowania**
|
||||
|
||||
Zezwala na opcjonalne pełne (e2ee) szyfrowanie treści za pomocą wspólnego tajnego klucza.
|
||||
Stadardowo, prywatne wiadomości są szyfrowane podczas transportu i przechowywania. W dzisiejszych czasach to szyfrowanie może nie wystarczyć, jeśli twoja komunikacja jest wyjątkowo wrażliwa. Ta opcja umożliwia dodatkowo szyfrowanie treści "end-toend" za pomocą wspólnego tajnego klucza. Sposób, w jaki odbiorca pozna tajny klucz, zależy wyłącznie od Ciebie. Możesz podać wskazówkę, na przykład "imię pierwszego psa cioci Kloci".
|
||||
|
||||
**Wyłączenie komentarzy**
|
||||
|
||||
Zapewnia możliwość wyłączenia komentowania wpisu
|
||||
|
||||
**Opóźnione publikowanie**
|
||||
|
||||
Pozwala na publikację wpisów w późniejszym terminie
|
||||
|
||||
**Wygasanie treści**
|
||||
|
||||
Usuwanie wpisów, komentarzy albo prywatnych wiadomości w określonym terminie. Do edytora wpisów zostaje dodany dodatkowy przycisk, za pomoca któreg można ustawić termin wygaśnięcia publikacji. Zwykle data jest wyświetlana w formacie „rrrr-mm-dd gg: mm”, ale w języku angielskim ma się nieco większą swobodę i można używać większości rozpoznawalnych odniesień do dat, takich jak "next Thursday" czy "+1 day". W określonym terminie (podanym lub zajmującym około dziesięciu minut, w zależności od częstotliwości sprawdzania zdalnego systemu) element jest usuwany.
|
||||
|
||||
**Pomijaj zduplikowane wpisy i komentarze**
|
||||
|
||||
Zapobiegaj publikowaniu wpisów o identycznej treści, mających mniej niż dwie minuty między przesłaniami.
|
||||
|
||||
**Automatyczne zapisywanie roboczych wpisów i komentarzy**
|
||||
|
||||
Automatycznie zapisuje wersje robocze wpisów i komentarzy w lokalnej pamięci przeglądarki, aby zapobiec przypadkowej utracie kompozycji.
|
||||
|
||||
|
||||
#### Zarządzanie
|
||||
|
||||
**Wybór kanału poprzez nawigację**
|
||||
|
||||
Zmiana kanału bezpośrednio z rozwijanego menu nawigacji.
|
||||
|
||||
#### Sieć
|
||||
|
||||
**Filtr wydarzeń**
|
||||
|
||||
Możliwość wyświetlania tylko wydarzeń.
|
||||
|
||||
**Filtr ankiet**
|
||||
|
||||
Możliwość wyświetlania tylko ankiet.
|
||||
|
||||
**Zapisywane wyszukiwanie**
|
||||
|
||||
Możliwość zapisywania wyszukiwanych haseł do ponownego wykorzystania.
|
||||
|
||||
**Zapisywane foldery**
|
||||
|
||||
Możliwość umieszczania wpisów w folderach
|
||||
|
||||
**Alternatywan kolejność strumienia**
|
||||
|
||||
Możliwość uporządkowania strumienia według daty ostatniego wpisu, daty ostatniego komentarza lub nieprzeczytanych aktywności.
|
||||
|
||||
**Filtr kontaktów**
|
||||
|
||||
Możliwość wyświetlania wpisów autorstwa tylko wybranego kontaktu.
|
||||
|
||||
**Filtr forów**
|
||||
|
||||
Możliwość wyświetlania wpisów tylko z określonego forum.
|
||||
|
||||
**Filtr wpisów osobistych**
|
||||
|
||||
Filtr wpisów osobistych.
|
||||
|
||||
**Użyj trybu blog/lista**
|
||||
|
||||
Pozwoduje, że komentarze są wyświetlane osobno.
|
||||
|
||||
#### Zdjęcia
|
||||
|
||||
**Lokalizowanie zdjęć**
|
||||
|
||||
Jeśli dane lokalizacji są dostępne na przesłanych zdjęciach, połącz je z mapą.
|
||||
|
||||
##### Profile
|
||||
|
||||
**Profile zaawansowane**
|
||||
|
||||
Dodatkowe sekcje i pola wyboru profilu. Rozszerza to zakres informacji profilowych zbieranych w serwisie. Włączenie tej funkcjonalności powinno znaleźć odzwierciedlenie w dokumencie "Polityka prywatności", w której należy wymienić wszystkie rodzaje informacji osobistych zbieranych i utrzymywanych w serwisie. W większości przypadków jest to funkcjonalność nieprzydatna i nie powinno się jej włączać.
|
||||
|
||||
**Import/Eksport proflilu**
|
||||
|
||||
Możliwość zaimportowania lub wyeksportowania swojego profilu na inne serwisy (węzły sieci Zot). Funkcjonalność ta związana jest z nomadycznością tożsamości internetowej w $Projectname. Domyślnie Twoja tożsamość "podróżuje" z Tobą, gdy przeglądasz matrycę zdalnych witryn - tam też wiedzą kim jesteś i mogą wyświetlać Ci treści, które tylko Ty widzisz. Dzięki rozszerzonemu udostępnianiu tożsamości możesz dostarczyć te informacje do dowolnej odwiedzanej witryny z poziomu swojej matrycy.
|
||||
|
||||
**Wiele profili**
|
||||
|
||||
Możliwość tworzenia wielu profili, które są widoczne tylko dla określonych osób lub grup. Twój profil domyślny może być widoczny dla każdego, ale wszystkie profile dodatkowe mogą zawierać inne lub dodatkowe informacje i mogą być widoczne tylko dla tych, do których jest przypisany.
|
||||
|
||||
**Strony internetowe**
|
||||
|
||||
Zapewnia możliwość korzystania z funkcji projektowania stron internetowych i tworzenia niestandardowych stron internetowych na podstawie własnej zawartości, a także projektowania stron z układami stron, niestandardowymi elemntami menu i blokami treści.
|
||||
Dodatkowe ustawienia dostępne tylko z wiersza poleceń
|
||||
-----------------------------------------------------
|
||||
|
||||
Oprócz opcji konfiguracyjnych dostępnych w panelu administracyjnum, $Projectname zawiera wiele opcji, które są dostępne tylko z poziomu powłoki. Są to na ogół opcje uważane za zbyt niszowe, zaawansowane lub mogące być źle interpretowane przez zwykłych użytkowników.
|
||||
|
||||
**Prywatne notatki**
|
||||
Ich omówienie znajduje się na stronie [Zaawanasowana konfiguracja dla administratorów](/doc/pl/hidden_configs).
|
||||
|
||||
Na stronach, na których jest to dostępne (Twoja matryca i osobiste strony internetowe), zapewnia widżet do tworzenia i przechowywania osobistych przypomnień i notatek.
|
||||
|
||||
**Ulepszone albumy ze zdjęciami**
|
||||
|
||||
Zapewnia przeglądarkę albumów zdjęć, która ma nieco ładniejszy interfejs niż zwykły album.
|
||||
|
||||
**Rozszerzone udostępnianie tożsamości**
|
||||
|
||||
Domyślnie Twoja tożsamość "podróżuje" z Tobą, gdy przeglądasz matrycę zdalnych witryn - tam też wiedzą kim jesteś i mogą wyświetlać Ci treści, które tylko Ty widzisz. Dzięki rozszerzonemu udostępnianiu tożsamości możesz dostarczyć te informacje do dowolnej odwiedzanej witryny z poziomu swojej matrycy.
|
||||
|
||||
**Tryb ekspercki**
|
||||
|
||||
Pozwala to zobaczyć niektóre zaawansowane opcje konfiguracji, które mogą dezorientować niektóre osoby lub powodować problemy z obsługą. Funkcjonalność ta może zapewnić pełną kontrolę nad funkcjami i kolorami motywu - dzięki czemu można dostosować dużą liczbę ustawień motywu wyświetlania do własnych upodobań.
|
||||
|
||||
**Kanał Premium**
|
||||
|
||||
Dzięki temu możesz ustawić ograniczenia i warunki dotyczące tych, które łączą się z Twoim kanałem. Może to być używane przez celebrytów lub kogoś, kto chce postawić jakieś warunki osobom, które chcą się połączyć z tym kanałe. Jednym z warunków moze byc dokonanie płatności za połączenie.
|
||||
|
||||
**Edytor tekstu formatowanego**
|
||||
|
||||
Edytor postów dostępny z poziomy matrycy jest edytorem zwykłego tekstu, ale matryca pozwala na stosowanie szerokieo zakresu znaczników przy użyciu BBcode. Edytor wizualny jest natomiast edytorem WYSIWIG (what you see is what you get - otrzymujesz to, co widzisz)i zapewnia wszystkie najczęściej używane znaczniki BBcode.
|
||||
|
||||
**Podgląd wpisu**
|
||||
|
||||
Umożliwia podgląd postów i komentarzy dokładnie tak, jak wyglądałyby na stronie przed ich opublikowaniem.
|
||||
|
||||
**Źródła kanałów**
|
||||
|
||||
Automatycznie importuje i ponownie publikuje zawartość kanału z innych kanałów lub źródeł. Umożliwia to tworzenie podkanałów i superkanałów z treści publikowanych gdzie indziej. Zasady są takie, że treść musi być publiczna, a właściciel kanału musi udzielić Ci pozwolenia na pozyskiwanie swojego kanału.
|
||||
|
||||
**Jeszcze więcej szyfrowania**
|
||||
|
||||
Stadardowo, prywatne wiadomości są szyfrowane podczas transportu i przechowywania. W dzisiejszych czasach to szyfrowanie może nie wystarczyć, jeśli twoja komunikacja jest wyjątkowo wrażliwa. Ta opcja umożliwia dodatkowo szyfrowanie treści "end-toend" za pomocą wspólnego tajnego klucza. Sposób, w jaki odbiorca pozna tajny klucz, zależy wyłącznie od Ciebie. Możesz podać wskazówkę, na przykład "imię pierwszego psa cioci Kloci".
|
||||
|
||||
**Wyszukiwanie wg daty**
|
||||
|
||||
Daje to możliwość wybierania postów według zakresów dat
|
||||
|
||||
**Filtr grup prywatności**
|
||||
|
||||
Włączenie tego widżetu umożliwia wyświetlanie strumienia postów tylko z wybranych grup połączeń. Powoduje to również przełączenie uprawnień wychodzących podczas przeglądania grupy prywatności. Jest to podobne do "kręgów" Google czy też "aspektów" w Disaporze.
|
||||
|
||||
**Zapisane wyszukiwania**
|
||||
|
||||
Udostępnia widżet wyszukiwania na stronie matrycy, który może zapisywać wybrane frazy wyszukiwania do ponownego wykorzystania.
|
||||
|
||||
**Zakładka Osobiste**
|
||||
|
||||
Włącz tą kartę, aby wyświetlać tylko wpisy matrycowe, z którymi w jakiś sposób wchodziłeś w interakcję, jako autor lub współautor konwersacji.
|
||||
|
||||
**Zakładka Nowy**
|
||||
|
||||
Włącza tą kartę, aby wyświetlać wszystkich nowych działania matrycy jako węża strażackiego lub osi czasu.
|
||||
|
||||
**Narzedzia zaprzyjaźnienia**
|
||||
|
||||
Filtrowanie aktywności strumienia matrycy według głębokości relacji.
|
||||
|
||||
**Edytuj wysłane posty**
|
||||
|
||||
Mozliwość edytowania i poprawiania postów i komentarzy juz po wysłaniu.
|
||||
|
||||
**Tagowanie**
|
||||
|
||||
Możliwość tagowania istniejących postów, w tym napisanych przez innych.
|
||||
|
||||
**Kategorie postów**
|
||||
|
||||
Możliwość dodawania kategorie do postów na swoim kanale
|
||||
|
||||
**Zapisane foldery**
|
||||
|
||||
Możliwość umieszczania postów w folderach lub tagach do późniejszego przywołania.
|
||||
|
||||
**Dezaprobata postów**
|
||||
|
||||
Możliwość dezaprobaty ("niepolubienia") wpisów i komentarzy.
|
||||
|
||||
**Gwiazdkowanie postów**
|
||||
|
||||
Możliwość oznaczania specjalnych postów znakiem gwiazdki
|
||||
|
||||
**Chmura tagów**
|
||||
|
||||
Udostępnienie osobistej chmury tagów na stronie swojego kanału
|
||||
|
||||
#include doc/macros/pl/main_footer.bb;
|
||||
|
||||
260
doc/pl/Plugins.md
Normal file
260
doc/pl/Plugins.md
Normal file
@@ -0,0 +1,260 @@
|
||||
|
||||
Tworzenie wtyczek (dodatków) do $Projectname
|
||||
============================================
|
||||
|
||||
Przypuszczalnie chcesz, aby $Projectname zrobił coś, czego jeszcze nie robi. Jest wiele sposobów. Ale nauczmy się, jak napisać wtyczkę lub dodatek.
|
||||
|
||||
W katalogu $Projectname prawdopodobnie zobaczysz podkatalog o nazwie "addon". Jeśli jeszcze go nie masz, utwórz go.
|
||||
|
||||
mkdir addon
|
||||
|
||||
Następnie wymyśl nazwę swojego dodatku. Prawdopodobnie masz już jakieś pojęcie o tym, co chcesz, aby robił. Na potrzeby naszego przykładu utworzymy wtyczkę o nazwie "randplace", która zapewni nieco losową lokalizację każdego z Twoich wpisów. Nazwa wtyczki będzie służyć do znajdowania funkcji, które trzeba użyć i jest częścią nazwy każdej z tychfunkcji, więc dla bezpieczeństwa używaj tylko prostych znaków tekstowych.
|
||||
|
||||
Po wybraniu nazwy wtyczki, utwórz katalog wewnątz 'addon', aby przechowywać tu pliki wtyczki.
|
||||
|
||||
mkdir addon/randplace
|
||||
|
||||
|
||||
Teraz utwórz plik wtyczki. Musi mieć taką samą nazwę i jest to skrypt PHP, więc za pomocą swojego ulubionego edytora utwórz plik
|
||||
|
||||
addon/randplace/randplace.php
|
||||
|
||||
Pierwszą linią tego pliku musi być fraza
|
||||
|
||||
<?php
|
||||
|
||||
Następnie utworzymy blok komentarza, aby opisać wtyczkę. Jest do tego specjalny format. Używamy / * ... * / w stylu komentarza i niektórych oznaczonych linii składających się z
|
||||
|
||||
/**
|
||||
*
|
||||
* Name: Random Place (here you can use better descriptions than you could in the filename)
|
||||
* Description: Sample $Projectname plugin, Sets a random place when posting.
|
||||
* Version: 1.0
|
||||
* Author: Mike Macgirvin <mike@zothub.com>
|
||||
*
|
||||
*/
|
||||
|
||||
Te atrybuty będą widoczne dla administratora strony, gdy instaluje lub zarządza wtyczkami z panelu administracyjnego. Może być więcej autorów. W takim przypadku, po prostu dodaj kolejną linię zaczynającą się od "Autor:".
|
||||
|
||||
Typowa wtyczka będzie miała co najmniej następujące funkcje:
|
||||
|
||||
* pluginname_load()
|
||||
* pluginname_unload()
|
||||
|
||||
W naszym przypadku nazwiemy je `randplace_load()` i `randplace_unload()`, bo taka jest nazwa naszej wtyczki. Te funkcje są wywoływane za każdym razem, gdy chcemy zainicjować wtyczkę lub usunąć ją z bieżącej strony internetowej. Również jeśli wtyczka wymaga rzeczy takich jak zmiana schematu bazy danych przed uruchomieniem jej po raz pierwszy, trzeba będzie umieścić poniższe funkcje:
|
||||
|
||||
* pluginname_install()
|
||||
* pluginname_uninstall()
|
||||
|
||||
Następnie omówimy **zaczepy**. Zaczepy (*ang. hooks*) to miejsca w kodzie $Projectname, do których można "podczepić" kod wtyczki, aby go tam wykonywać. Zwykle wykorzystuje się funkcję `pluginname_load()` do zarejestrowania "funkcji obsługi" dla potrzebnych zaczepów. Następnie, gdy zostanie wyzwolony którykolwiek z tych zaczepów, zostanie wywołany podpięty tam kod.
|
||||
|
||||
Zarejestrujmy więc program obsługi zaczepów za pomocą funkcji `register_hook()`. Potrzebne są trzy argumenty. Pierwszy to nazwa zaczepu, który chcemy obsłużyć, drugi to nazwa pliku, który ma znaleźć naszą funkcję obsługi (ścieżka względem katalogu instalacyjnego $Projectname), a trzeci to nazwa funkcji. Stwórzmy więc teraz naszą funkcję `randplace_load()`.
|
||||
|
||||
```
|
||||
function randplace_load() {
|
||||
register_hook('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
|
||||
|
||||
register_hook('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
|
||||
register_hook('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
|
||||
}
|
||||
```
|
||||
|
||||
Tak więc przechwycimy trzy zdarzenia: `post_local`, które jest wywoływane, gdy w systemie lokalnym pojawia się wpis, `feature_settings`, aby ustawić pewne preferencje dla naszej wtyczki, oraz `feature_settings_post`, aby przechowywać te ustawienia.
|
||||
|
||||
Następnie utworzymy funkcję unload. Jest to łatwe, ponieważ wystarczy wyrejestrować nasze zaczepy. Wymaga to dokładnie tych samych argumentów.
|
||||
|
||||
```
|
||||
function randplace_unload() {
|
||||
unregister_hook('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
|
||||
unregister_hook('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
|
||||
unregister_hook('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
|
||||
}
|
||||
```
|
||||
Zaczepy są wywoływane z dwoma argumentami. Pierwszą to zawsze $a, który jest naszą globalną strukturą aplikacji i zawiera ogromną ilość informacji o stanie przetwarzanego żądania HTTP; a także o tym kim jest przeglądający i jaki jest nasz stan logowania oraz aktualną zawartość strony internetowej, którą prawdopodobnie tworzymy.
|
||||
|
||||
Drugi argument jest specyficzny dla zaczepu, który chce się wywołać. Zawiera informacje istotne dla tego konkretnego miejsca w programie i często pozwala na jego przegląd a nawet zmianę. Aby to zmienić, trzeba dodać zanak "&" do nazwy zmiennej, aby była przekazywana do funkcji przez odniesienie. W przeciwnym razie utworzona zostanie kopia i wszelkie wprowadzone zmiany zostaną utracone przy ponownym przetworzeniu zaczepu. Zwykle (ale nie zawsze) drugim argumentem jest nazwana tablica struktur danych.
|
||||
|
||||
Dodajmy więc poniższy kod, aby zaimplementować nasz moduł obsługi zaczepu:
|
||||
|
||||
```
|
||||
function randplace_post_hook($a, &$item) {
|
||||
|
||||
/**
|
||||
*
|
||||
* W systemie lokalnym został wpisany jakiś element.
|
||||
* Będziemy wyszukiwać określonych elementów:
|
||||
* - Wpis napisany przez właściciela profilu
|
||||
* - Właściciel profilu musi zezwolić na naszą wtyczkę
|
||||
*
|
||||
*/
|
||||
|
||||
logger('randplace invoked');
|
||||
|
||||
if(! local_channel()) /* nie zero jeśli zalogowany jest użytkownik systemu */
|
||||
return;
|
||||
|
||||
if(local_channel() != $item['uid']) /* Czy ta osoba jest właścicielem wpisu? */
|
||||
return;
|
||||
|
||||
if(($item['parent']) || (! is_item_normal($item))) {
|
||||
/* Jeśli element ma rodzica lub nie jest „normalny”, jest to komentarz lub coś innego, a nie wpis. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pobranie osobistych ustawień konfiguracyjnych */
|
||||
|
||||
$active = get_pconfig(local_channel(), 'randplace', 'enable');
|
||||
|
||||
if(! $active)
|
||||
return;
|
||||
/**
|
||||
*
|
||||
* OK, wolno nam robić swoje.
|
||||
* Oto, co zamierzamy zrobić:
|
||||
* załadowanie listy nazw stref czasowych i użycie jej do wygenerowania listy miast na świecie.
|
||||
* Następnie wybierzemy losowo jedno z nich i umieścimy je w polu "location" wpisu.
|
||||
*
|
||||
*/
|
||||
|
||||
$cities = array();
|
||||
$zones = timezone_identifiers_list();
|
||||
foreach($zones as $zone) {
|
||||
if((strpos($zone,'/')) && (! stristr($zone,'US/')) && (! stristr($zone,'Etc/')))
|
||||
$cities[] = str_replace('_', ' ',substr($zone,strpos($zone,'/') + 1));
|
||||
}
|
||||
|
||||
if(! count($cities))
|
||||
return;
|
||||
$city = array_rand($cities,1);
|
||||
$item['location'] = $cities[$city];
|
||||
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
Teraz dodajmy nasze funkcje do ustawień preferencji tworzenia i przechowywania.
|
||||
|
||||
```
|
||||
/**
|
||||
*
|
||||
* Wywołanie zwrotne z funkcji ustawień wpisu.
|
||||
* $post zawiera globalną tablicę $_POST.
|
||||
* Upewnimy się, że mamy ważne konto użytkownika
|
||||
* i że kliknięto tylko nasz własny przycisk submit
|
||||
* a jeśli tak, to ustawiamy ustawienia konfiguracyjne dla tego użytkownika.
|
||||
*
|
||||
*/
|
||||
|
||||
function randplace_settings_post($a,$post) {
|
||||
if(! local_channel())
|
||||
return;
|
||||
if($_POST['randplace-submit'])
|
||||
set_pconfig(local_channel(),'randplace','enable',intval($_POST['randplace']));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Wywoływanie z formularza ustawień funkcjonalności.
|
||||
* Drugim argumentem jest w tym przypadku łańcuch, region treści HTML strony.
|
||||
* Dodanie własnych informacje o ustawieniach do tego łańcucha.
|
||||
*
|
||||
* Aby zapewnić jednolitość stron ustawień, stosujemy następującą konwencję
|
||||
* <div class="settings-block">
|
||||
* <h3>title</h3>
|
||||
* .... settings html - będzie wiele elementów pływających ...
|
||||
* <div class="clear"></div> <!-- klasa ogólna, która czyści wszystkie elementy pływające -->
|
||||
* <input type="submit" name="pluginnname-submit" class="settings-submit" ..... />
|
||||
* </div>
|
||||
*/
|
||||
|
||||
function randplace_settings(&$a,&$s) {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
/* Dodanie naszego arkusza stylów do strony, aby ładnie wyglądała strona ustawień */
|
||||
|
||||
head_add_css('/addon/randplace/randplace.css');
|
||||
|
||||
/* Pobranie aktualnego stan naszej zmiennej konfiguracyjnej */
|
||||
|
||||
$enabled = get_pconfig(local_channel(),'randplace','enable');
|
||||
|
||||
$checked = (($enabled) ? ' checked="checked" ' : '');
|
||||
|
||||
/* Dodaj trochę HTML do istniejącego formularza */
|
||||
|
||||
$s .= '<div class="settings-block">';
|
||||
$s .= '<h3>' . t('Randplace Settings') . '</h3>';
|
||||
$s .= '<div id="randplace-enable-wrapper">';
|
||||
$s .= '<label id="randplace-enable-label" for="randplace-checkbox">' . t('Enable Randplace Plugin') . '</label>';
|
||||
$s .= '<input id="randplace-checkbox" type="checkbox" name="randplace" value="1" ' . $checked . '/>';
|
||||
$s .= '</div><div class="clear"></div>';
|
||||
|
||||
/* dodanie przycisku przesyłania */
|
||||
|
||||
$s .= '<div class="settings-submit-wrapper" ><input type="submit" name="randplace-submit" class="settings-submit" value="' . t('Submit') . '" /></div></div>';
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
***Zaawansowane wtyczki***
|
||||
|
||||
Czasami zachodzi potrzeba zapewnienia jakichś nowych funkcji, których w ogóle nie ma lub których nie można zapewnić za pomocą zaczepów. W tym przypadku wtyczka może również działać jako "moduł". Moduł w naszym przypadku odnosi się do ustrukturyzowanej procedury obsługi strony internetowej, która odpowiada na podany adres URL. Wtedy wszystko, co uzyskuje dostęp do tego adresu URL, będzie obsługiwane w całości przez wtyczkę.
|
||||
|
||||
Kluczem do tego jest stworzenie prostej funkcji o nazwie `pluginname_module()`, która nic nie robi.
|
||||
|
||||
```
|
||||
function randplace_module() { return; }
|
||||
```
|
||||
|
||||
Gdy ta funkcja już istnieje, adres URL https://twoja_witryna/randplace będzie uzyskiwał dostęp do wtyczki jako modułu. Następnie możesz zdefiniować funkcje, które są wywoływane w różnych miejscach w celu zbudowania strony internetowej, tak jak moduły w katalogu mod/. Oto typowe funkcje i kolejność ich wywoływania
|
||||
|
||||
```
|
||||
modulename_init($a) // (e.g. randplace_init($a);) wywoływana jako pierwsza.
|
||||
// Gdy chce się emitować json lub xml, powinno się to
|
||||
// zrobić tutaj, a następnie wywołać killme(), co pozwoli
|
||||
// uniknąć domyślnej akcji budowania strony internetowej.
|
||||
modulename_aside($a) // często uzywana di tworzenia zawartości paska bocznego
|
||||
modulename_post($a) // wywoływana za każdym razem, gdy strona jest otwierana
|
||||
// za pomocą metody "post"
|
||||
modulename_content($a) // wywoływana w celu wygenerowania zawartości strony centralnej.
|
||||
// Ta funkcja powinna zwracać łańcuch znaków składający się
|
||||
// z centralnej yteści strony.
|
||||
```
|
||||
|
||||
Funkcje modułu mają dostęp do ścieżki URL tak, jakby były samodzielnymi programami w systemie operacyjnym Unix. Dla przykładu, w naszego module stwórzmy coś co działa pod adresem:
|
||||
|
||||
https://yoursite/randplace/something/somewhere/whatever
|
||||
|
||||
Bedzie to listę argc i argv do wykorzystania przez funkcje tego modułu
|
||||
|
||||
```
|
||||
$x = argc(); $x will be 4, the number of path arguments after the sitename
|
||||
|
||||
for($x = 0; $x < argc(); $x ++)
|
||||
echo $x . ' ' . argv($x);
|
||||
|
||||
0 randplace
|
||||
1 something
|
||||
2 somewhere
|
||||
3 whatever
|
||||
```
|
||||
|
||||
***Przenoszenie wtyczek Friendica***
|
||||
|
||||
$Projectname wykorzystuje podobną architekturę wtyczek do projektu Friendica. Mechanizmy uwierzytelniania, tożsamości i uprawnień są zupełnie inne. Wiele wtyczek Friendica można stosunkowo łatwo przenosić, zmieniając nazwy kilku funkcji i następnie zapewniając przestrzeganie modelu uprawnień. Funkcje, których nazwy wymagają zmiany, to:
|
||||
|
||||
* Funkcja Friendica `pluginname_install()` to `pluginname_load()`
|
||||
|
||||
* Funkcja Friendica `pluginname_uninstall()` to `pluginname_unload()`
|
||||
|
||||
$Projectname ma funkcje `_install` i `_uninstall`, ale są one używane w inny sposób.
|
||||
|
||||
* Funkcja zaczepu w Friendica `plugin_settings` ma nazwę `feature_settings`
|
||||
|
||||
* Funkcja zaczepu Friendica `plugin_settings_post` ma nazwę `feature_settings_post`
|
||||
|
||||
Zmiana tych ustawień często pozwoli na działanie wtyczki, ale proszę dokładnie sprawdzić wszystkie uprawnienia i kod identyfikacyjny, ponieważ koncepcje, które za tym stoją, są zupełnie inne w $Projectname. Wiele nazw danych strukturalnych (zwłaszcza kolumny schematu bazy danych) jest również zupełnie inna.
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
43
doc/pl/Primary-Directory.md
Normal file
43
doc/pl/Primary-Directory.md
Normal file
@@ -0,0 +1,43 @@
|
||||
#Katalog główny#
|
||||
|
||||
Domyślnie $Projectname używa katalogów dostępnych w Internecie, które funkcjonują jako kanały.
|
||||
|
||||
Istnieją pewne scenariusze, w których może być potrzebny własny serwer katalogów, do którego można by podłączyć wiele węzłów. Ogranicza to dostęp tylko do kanałów w węzłach podłączonych do tego serwera katalogowego.
|
||||
|
||||
##Instrukcje dotyczące konfigurowania jednego węzła jako katalogu podstawowego dla wielu węzłów prywatnych.##
|
||||
***
|
||||
|
||||
|
||||
* W węźle, który będzie serwerem katalogów, otwórz plik .htconfig.php i ustaw:
|
||||
|
||||
`App::$config['system']['directory_mode'] = DIRECTORY_MODE_PRIMARY;`
|
||||
|
||||
|
||||
Domyślnie, opcja ta powinna już być ustawiona na **DIRECTORY_MODE_NORMAL**, więc po prostu wystarczy tylko ustawić nową wartość: **DIRECTORY_MODE_PRIMARY**
|
||||
|
||||
* Następnie, w każdym węźle (w tym na serwerze katalogowym), w terminalu, przejdź do folderu, w którym jest zainstalowany kod węzła i uruchomić usługę katalogową:
|
||||
|
||||
`util/config system directory_realm YOURREALMNAME`
|
||||
|
||||
(**YOURREALMNAME** może być dowolną nazwą dziedziny katalogowej)
|
||||
|
||||
po czym:
|
||||
|
||||
`util/config system realm_token THEPASSWORD`
|
||||
|
||||
(**THEPASSWORD** jest hasłem dla dziedziny katalogowej)
|
||||
|
||||
**UWAGA:** Trzeba użyć tej samej nazwy dziedziny i hasła dla każdego węzła
|
||||
|
||||
* Na koniec, dla każdego węzła "klienckiego", uruchom (z terminala):
|
||||
|
||||
`util/config system directory_server https://theaddressofyourdirectoryserver.com`
|
||||
|
||||
***
|
||||
Teraz, gdy przeglądasz katalog każdego węzła, powinien on pokazywać tylko kanały, które istnieją w węzłach ustawionej domeny katalogowej. Do tej pory testowałem to z dwoma węzłami i wydaje się, że działa dobrze.
|
||||
Kanały utworzone w każdym węźle są odzwierciedlane w katalogu głównym, a następnie w katalogu wszystkich węzłów klienckich
|
||||
|
||||
##Problemy##
|
||||
***
|
||||
|
||||
Kiedy tworzyłem pierwszy węzeł, był on uruchomiony i działał przez około godzinę, zanim zmieniłem go na PRIMARY_MODE, a po zmianie w katalogu nadal było kilka kanałów z całej matrycy. Usunąłem je z tabeli xchan i wydaje się, że rozwiązało to problem.
|
||||
@@ -1,56 +1,80 @@
|
||||
Tłumaczenie $Projectname
|
||||
========================
|
||||
|
||||
Procedura tłumaczenia
|
||||
---------------------
|
||||
Procedura tłumaczenia na język polski
|
||||
-------------------------------------
|
||||
|
||||
Ciągi używane w interfejsie użytkownika $Projectname są tłumaczone
|
||||
w [Transifex][1], a następnie przeniesione do repozytorium Git na
|
||||
github. Jeśli chcesz pomóc w tłumaczeniu dla dowolnego języka, czy
|
||||
to poprawianie warunków, czy tłumaczenie $Projectname na plik aktualnie
|
||||
nieobsługiwany język, zarejestruj konto na transifex.com i skontaktuj
|
||||
się z tamtejszym zespołem tłumaczy Redmatrix.
|
||||
Tłumaczenie interfejsu użytkownika, ekranów kontekstowej pomocy oraz dokumentacji
|
||||
na język polski odbiega nieco od ogólnej procedury przyjetej w $Projectname.
|
||||
Po prostu, zrezygnowano z przygotowania pliku translacyjnego hmessages.po
|
||||
za pośrednictwem serwisu [Transifex][1], tak jak to jest zalecane w $Projectname
|
||||
i posłużono się sporządzeniem tych plików przy pomocy ogólnie dostępnych narzędzi
|
||||
translacyjnych przeznaczonych do tworzenia plików [gettext](https://www.gnu.org/software/gettext/) (rozszerzenia .po, .mo, .pot), takich jak [poedit](https://poedit.net/) i inne.
|
||||
|
||||
Tłumaczenie $Projectname jest proste. Po prostu użyj narzędzia online
|
||||
w transifex. Jeśli nie chcesz mieć do czynienia z git & co. w porządku,
|
||||
regularnie sprawdzamy status tłumaczeń i importujemy je do drzewa
|
||||
źródłowego na github, aby inni mogli z nich korzystać.
|
||||
Trzeba podkreślić, że to odstępstwo dotyczy przygotowania pliku hmessages.po
|
||||
i organizacji prac nad tłumaczeniem.
|
||||
|
||||
Nie uwzględniamy każdego tłumaczenia z transifex w drzewie źródłowym,
|
||||
aby uniknąć rozproszonego i zakłóconego ogólnego doświadczenia. Jako
|
||||
niewykształcone przypuszczenie mamy dolną granicę 50% przetłumaczonych
|
||||
ciągów, zanim włączymy język. Limit ten jest oceniany tylko na podstawie
|
||||
ilości przetłumaczonych ciągów przy założeniu, że najbardziej widoczne
|
||||
ciągi dla interfejsu użytkownika zostaną przetłumaczone jako pierwsze
|
||||
przez zespół tłumaczący. Jeśli uważasz, że Twoje tłumaczenie będzie
|
||||
przydatne przed tym limitem, skontaktuj się z nami, a prawdopodobnie
|
||||
uwzględnimy pracę Twoich zespołów w drzewie źródłowym.
|
||||
Tłumaczenie $Projectname na język polski jest obecnie wydzielone w odrębny podprojekt,
|
||||
utrzymywany w [repozytorium na GitHub](https://github.com/astabski/hubzilla-pl)
|
||||
|
||||
Jeśli chcesz samodzielnie przenieść swoją pracę do drzewa źródłowego,
|
||||
zrób to i skontaktuj się z nami i zadaj pytanie, które się pojawi.
|
||||
Proces jest prosty, a oprogramowanie $Projectname jest dostarczane ze wszystkimi
|
||||
niezbędnymi narzędziami.
|
||||
Projekt ten obejmuje wszystkie pliki potrzebne do przetłumaczenia interfesju użytkownika,
|
||||
pomocy kontekstowej i oficjalnej dokumentacji, zawarte w następujących katalogach
|
||||
kodu $Projectname:
|
||||
|
||||
Lokalizacją przetłumaczonych plików jest w drzewie źródłowym katalog
|
||||
`/view/LNG-CODE/`, ggdzie LNG-CODE jest używanym kodem języka, np.
|
||||
`de` dla niemieckiego lub `fr` dla francuskiego.
|
||||
W przypadku szablonów wiadomości e-mail (pliki `*.tpl`) po prostu umieść
|
||||
je w katalogu i gotowe. Przetłumaczone łańcuchy pochodzą z pliku
|
||||
"hmessages.po" z transifex, który należy przetłumaczyć na plik PHP
|
||||
używany przez $Projectname. Aby to zrobić, umieść plik w wymienionym
|
||||
wyżej katalogu i użyj narzędzia `po2php` z katalogu `util` w instalacji
|
||||
$Projectname.
|
||||
- view/pl
|
||||
- doc/context/pl
|
||||
- doc/macros/pl
|
||||
- doc/pl
|
||||
|
||||
Zakładając, że chcesz przetłumaczyć niemiecką wersję umieszczoną pliku
|
||||
`view/de/hmessages.po`, wykonaj następujące czynności.
|
||||
Projekt ten jest obecnie podstawą oficjalnego polskiego tłumaczenia $Projectname.
|
||||
Po każdej istotnej zmianie, osoba kierująca projektem tłumaczenia zgłasza odpowiednie
|
||||
żądanie PR do drzewa żródłowego $Projectname.
|
||||
|
||||
### Zgłaszanie poprawek
|
||||
|
||||
Jeśli chcesz zgłosić jakieś zmiany w istniejącym tekście tłumaczenia, otwórz
|
||||
nową sprawę na stronie https://github.com/astabski/hubzilla-pl/issues i podaj tam
|
||||
szczegóły proponowanych zmian.
|
||||
|
||||
Możesz też dokonać poprawek w tym projekcie, zgłaszając odpowiednio przygotowane
|
||||
żądanie PR.
|
||||
|
||||
### Nowe tłumaczenia
|
||||
|
||||
Jeśli chcesz pomóc, tworząc tłumaczenia jeszcze nie przetłumaczonych dokumentów
|
||||
$Projectname, dołącz do projektu https://github.com/astabski/hubzilla-pl. W tym
|
||||
celu umieść na stronie https://github.com/astabski/hubzilla-pl/issues odpowiednią
|
||||
wiadomość. Otrzymasz odpowiedź z dokładną instrukcją.
|
||||
|
||||
Ogólne zasady tłumaczeń obowiązujące w $Projectname
|
||||
---------------------------------------------------
|
||||
|
||||
Jeśli chcesz samodzielnie przenieść swoją pracę do drzewa źródłowego $Projectname,
|
||||
skontaktuj się z zespołem $Projectname i zadaj pytania.
|
||||
|
||||
Proces jest tłumaczenia prosty, a oprogramowanie $Projectname jest dostarczane ze
|
||||
wszystkimi niezbędnymi narzędziami.
|
||||
|
||||
Lokalizacją przetłumaczonych plików jest w kodzie źródłowym katalog `/view/LNG-CODE/`,
|
||||
gdzie `LNG-CODE` jest używanym kodem języka, np. `de` dla niemieckiego lub `fr`
|
||||
dla francuskiego.
|
||||
|
||||
W przypadku szablonów wiadomości e-mail (pliki `*.tpl`) po prostu trzeba umieścić
|
||||
je w katalogu i gotowe. Przetłumaczone łańcuchy pochodzą z pliku `hmessages.po`
|
||||
z serwisu Transifex, który należy przetłumaczyć na plik PHP używany przez $Projectname.
|
||||
Aby to zrobić, trzeba umieścić plik w wymienionym wyżej katalogu i użyć narzędzia
|
||||
`po2php` z katalogu `util` w instalacji $Projectname.
|
||||
|
||||
Zakładając, że chcesz przetłumaczyć polską wersję umieszczoną pliku
|
||||
`view/pl/hmessages.po`, wykonaj następujące czynności.
|
||||
|
||||
1. Przejdź w wierszu polecenia do katalogu głównego instalacji $Projectname
|
||||
|
||||
2. Wykonaj skrypt `po2php`, który jest umieszczono tłumaczenia dla pliku `hstrings.php`, który jest używany w $Projectname.
|
||||
|
||||
$> php util/po2php.php view/de/hmessages.po
|
||||
$> php util/po2php.php view/pl/hmessages.po
|
||||
|
||||
Dane wyjściowe skryptu zostaną umieszczone w `view/de/hstrings.php, gdzie
|
||||
Dane wyjściowe skryptu zostaną umieszczone w `view/de/hstrings.php, bo tam
|
||||
froemdoca oczekuje tego pliku, więc możesz natychmiast przetestować swoje
|
||||
tłumaczenie.
|
||||
|
||||
|
||||
171
doc/pl/Widgets.md
Normal file
171
doc/pl/Widgets.md
Normal file
@@ -0,0 +1,171 @@
|
||||
Rdzenne widżety
|
||||
===============
|
||||
|
||||
Niektóre z tych widżetów ma ograniczenia, które mogą ograniczać typ strony, na której można umieszczać widżet lub mogą wymagać logowania
|
||||
|
||||
|
||||
* clock - wyświetla aktualny czas
|
||||
* args: military (1 or 0) - use 24 hour time as opposed to AM/PM
|
||||
<br /> <br />
|
||||
|
||||
* profile - wyświetla boczny pasek profilu na stronach, które ładują profile (strony z pseudonimem w adresie URL)
|
||||
|
||||
* tagcloud - wyświetla tagcloud elementów strony
|
||||
|
||||
* args: count - liczba elementów do jednoczesnego wyświetlenia (domyślnie 24)
|
||||
<br /> <br />
|
||||
|
||||
* collections - selektor grupy prywatności dla aktualnie zalogowanego kanału
|
||||
|
||||
* args: mode - może to być "conversation", "group" albo "abook" w zależności od modułu
|
||||
<br /> <br />
|
||||
|
||||
* suggestions - sugestie znajomych dla aktualnie zalogowanego kanału
|
||||
|
||||
* follow - przedstawia pole tekstowe do śledzenia innego kanału
|
||||
|
||||
* notes - obszar prywatnych notatek dla aktualnie zalogowanego kanału, jeśli funkcja private_notes jest włączona
|
||||
|
||||
* savedsearch - wyszukiwanie sieci lub matrycy z zapisem - trzeba być zalogowanym i musi być włączona funkcjonalność savedsearch
|
||||
|
||||
* filer - wybór elementów pola ze strumienia sieci lub matrycy - musi się być zalogowanym
|
||||
|
||||
* archive - selektor zakresu dat dla stron sieci i kanałów
|
||||
* args: 'wall' - 1 or 0, ograniczenie do wpisów ściennych lub wpisów sieciowych/matrycowych (domyślnie)
|
||||
<br /> <br />
|
||||
|
||||
* fullprofile - taki sam jak obecny profil
|
||||
|
||||
* categories - filtr kategorii (strona kanału)
|
||||
|
||||
* tagcloud_wall - tagcloud tylko dla strony kanału
|
||||
* args: 'limit' - ilość tagów do wyświetlenie (domyślnie 50)
|
||||
<br /> <br />
|
||||
|
||||
* catcloud_wall - tagcloud dla kategorii stron kanału
|
||||
* args: 'limit' - liczba kategorii do wyświetlenia na jednej stronie (domyślnie 50)
|
||||
<br /> <br />
|
||||
|
||||
* affinity - suwak powinowactwa na stronie sieciowej, trzeba być zalogowanym
|
||||
|
||||
* settings_menu - menu paska bocznego dla strony ustawień, trzeba być zalogowanym
|
||||
|
||||
* mailmenu - menu paska bocznego dla strony z prywatnymi wiadomościami, trzeba sie zalogować
|
||||
|
||||
* design_tools - menu narzędzi projektowych do tworzenia stron internetowych, trzeba sie zalogować
|
||||
|
||||
* findpeople - narzędzia do wyszukiwania innych kanałów
|
||||
|
||||
* photo_albums - wyświetla listę albumów ze zdjęciami aktualnego właściciela strony za pomocą menu wyboru
|
||||
|
||||
* vcard - mini pasek boczny profilu dla osoby, którą się jest zainteresowanym (właściciel strony, cokolwiek)
|
||||
|
||||
* dirsafemode - narzędzie do wyboru katalogu - tylko na stronach katalogów
|
||||
|
||||
* dirsort - narzędzie do wyboru katalogu - tylko na stronach katalogów
|
||||
|
||||
* dirtags - narzędzie katalogowe - tylko na stronach katalogów
|
||||
|
||||
* menu_preview - wyświetlanie podgląd menu - tylko na stronach edycji menu
|
||||
|
||||
* chatroom_list - lista czatów dla właściciela strony
|
||||
|
||||
* bookmarkedchats - lista zakładek do czatów zebranych na tej stronie dla obecnego obserwatora
|
||||
|
||||
* suggestedchats - "ciekawe" czaty wybrane dla obecnego obserwatora
|
||||
|
||||
* item - wyświetla pojedynczą stronę internetową zgodnie z argumentem mid lub title
|
||||
* args:
|
||||
* channel_id - kanał, do którego należy treść, domyślnie jest to profile_uid
|
||||
* mid - message_id strony do wyświetlenia (musi być to strona internetowa a nie element konersacji)
|
||||
* title - argument title w adresie URL strony internetowej (musi zawierać tutuł lub mid)
|
||||
<br /> <br />
|
||||
|
||||
* photo - wyświetla pojedyncze zdjęcie
|
||||
* args:
|
||||
* url - adres URL zdjęcia, musu zawierać schemat http lub https
|
||||
* zrl - uwierzytelniony link zid
|
||||
* style - łańcuch stylu CSS
|
||||
<br /> <br />
|
||||
|
||||
* cover_photo - wyświetla zdjęcie okładkowe dla wybranego kanału
|
||||
* args:
|
||||
* channel_id - zastosowany kanał, domyślnie jest to profile_uid
|
||||
* style - łańcuch stylu CSS (domyślnie jest dynamicznie ustawiane na szerokość regionu)
|
||||
<br /> <br />
|
||||
|
||||
|
||||
* photo_rand - wyświetla losowe zdjęcie z jednego z albumów fotograficznych. Honorowane są uprawnienie dostępu do zdjęć
|
||||
* args:
|
||||
* album - nazwa albumu (bardzo gorąco zalecane, jeśli ma się dużo zdjęć)
|
||||
* scale - zazwyczaj 0 (oryginalna wielkość), 1 (1024px), 2, (640px) lub 3 (320px)
|
||||
* style - łańcuch stylu CSS
|
||||
* channel_id - jeśli nie Twój
|
||||
<br /> <br />
|
||||
|
||||
* random_block - wyświetlić losowy element blokowy z kolekcji narzędzi do projektowania stron internetowych. Honorowane są uprawnienia dostępu.
|
||||
* args:
|
||||
* contains - zwraca tylko bloki, które zawierają łańcuch cotains w nazwie bloku
|
||||
* channel_id - jeśłi nie Twój
|
||||
<br /> <br />
|
||||
|
||||
* tasklist - podać listę zadań lub spraw do załatwienia dla aktualnie zalogowanego kanału.
|
||||
* args:
|
||||
* all - jeśłi nie 0, to wyświetla ukończone zadania.
|
||||
<br /> <br />
|
||||
|
||||
* forums - podać listę połączonych forów publicznych z niewidocznymi liczbami dla aktualnie zalogowanego kanału.
|
||||
<br /> <br />
|
||||
|
||||
* activity - podać listę autorów nieprzeczytanych treści sieciowych dla aktualnie zalogowanego kanału.
|
||||
|
||||
* album - udostępnia widget zawierający pełny album ze zdjęciami z albumów należących do właściciela strony; może być zbyt duży, aby wyświetlić go w regionie paska bocznego, więc najlepiej jest zaimplementować to jako widżet obszaru treści.
|
||||
* args:
|
||||
* album - nazwa albumu
|
||||
* title - opcjonalny tytuł, używana jest nazwa albumu, jeśli nie jest dostęþna
|
||||
<br /> <br />
|
||||
|
||||
|
||||
Tworzenie własnych widżetów
|
||||
===========================
|
||||
|
||||
### Widżety oparty na klasie
|
||||
|
||||
Aby utworzyć widżet oparty, na przykład, na klasie o nazwie "slugfish", utwórz plik o następującej zawartości:
|
||||
|
||||
````
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
|
||||
class Slugfish {
|
||||
|
||||
function widget($args) {
|
||||
|
||||
... Wstaw tutaj kod widżetu.
|
||||
... Funkcja ta zwraca łańcuch, który jest treścią HTML widżetu.
|
||||
... $args to nazwa tablicy, która przekazuje sowolne zmienne [var] z edytora układu
|
||||
... Na przykład [widget=slugfish][var=count]3[/var][/widget] wypełni $args tak:
|
||||
... [ 'count' => 3 ]
|
||||
|
||||
}
|
||||
|
||||
````
|
||||
Wynikowy plik można umieścić w widget/Slugfish/Slugfish.php lub Zotlabs/SiteWidgets/Slugfish.php. Można go również połączyć z repozytorium git za pomocą pliku util/add_widget_repo.
|
||||
|
||||
### Tradycyjny widget oparty na funkcjach
|
||||
|
||||
Jeśli chcesz mieć widżet o nazwie, na przykład, "slugfish", utwórz `widget/widget_slugfish.php` zawierający
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
function widget_slugfish($args) {
|
||||
|
||||
.. wstaw tu kod widżetu. Zobacz powyższe informacje o widżetach opartych na klasie, aby uzyskać szczegółowe informacje.
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
@@ -1,7 +1,11 @@
|
||||
[h3]Co to jest $Projectname?[/h3]
|
||||
$Projectname to bezpłatny i otwartoźródłowy zestaw aplikacji i usług internetowych działających na specjalnym serwerze internetowym, zwanym "hubem", który może łączyć się z innymi hubami w sfederalizowanej sieci internetowej.
|
||||
$Projectname zapewnia użytkownikom zaawansowaną komunikację, tożsamości i usług kontroli dostępu, które bezproblemowo współpracują w różnych domenach i niezależnych witrynach internetowych. Pozwala użytkownikom [b]publicznie[/b] lub [b]prywatnie[/b] publikować treści za pośrednictwem "kanałów" (ang. channel), które są podstawowymi, zabezpieczonymi kryptograficznie tożsamościami zapewniającymi uwierzytelnianie niezależnie od hubów, które je hostują. To rewolucyjne wyzwolenie tożsamości online z poszczególnych serwerów i domen jest nazywane "tożsamością nomadyczną" i jest oparte na protokole Zot, nowej strukturze zdecentralizowanej kontroli dostępu ze szczegółowymi, rozszerzalnymi uprawnieniami.
|
||||
Z praktycznego punktu widzenia członków danego huba, korzystających z oprogramowania $Projectname, oferuje ono szereg znanych, zintegrowanych aplikacji i usług internetowych, w tym:
|
||||
$Projectname to bezpłatny i otwartoźródłowy zestaw aplikacji i usług internetowych działających na specjalnym serwerze internetowym, zwanym "węzłem", który może łączyć się z innymi węzłami w sfederalizowanej sieci internetowej.
|
||||
$Projectname zapewnia użytkownikom zaawansowaną komunikację, tożsamości i usługę kontroli dostępu, które bezproblemowo współpracują w różnych domenach i niezależnych
|
||||
serwisach internetowych. $Projectname pozwala użytkownikom publikować treści, [b]publicznie[/b] lub [b]prywatnie[/b], w swoich "kanałach" (ang. channels), które są zabezpieczonymi kryptograficznie tożsamościami zapewniającymi
|
||||
uwierzytelnianie uzytkowników niezależnie od węzłów, które hostują te kanały. To rewolucyjne uwolnienie tożsamości inernetowej z poszczególnych serwerów i domen jest nazywane "tożsamością nomadyczną" i jest oparte na protokole Zot - nowej strukturze
|
||||
zdecentralizowanej kontroli dostępu ze szczegółowymi, rozszerzalnymi uprawnieniami.
|
||||
Z praktycznego punktu widzenia członków danego węzła, korzystających z oprogramowania $Projectname, oferuje ono szereg znanych,
|
||||
zintegrowanych aplikacji i usług internetowych, w tym:
|
||||
[ul]
|
||||
[li]wątki dyskusyjne w sieciach społecznościowych[/li]
|
||||
[li]przechowywanie plików w chmurze[/li]
|
||||
@@ -9,23 +13,30 @@ Z praktycznego punktu widzenia członków danego huba, korzystających z oprogra
|
||||
[li]hosting stron internetowych z systemem zarządzania treścią[/li]
|
||||
[li]wiki[/li]
|
||||
[li]i dużo więcej ...[/li][/ul]
|
||||
Chociaż wszystkie te aplikacje i usługi można znaleźć w innych pakietach oprogramowania, tylko $Projectname pozwala ustawić uprawnienia dla grup i osób, [b]które mogą nawet nie mieć kont na Twoim hubie[/b]! W typowych aplikacjach internetowych, jeśli chcesz udostępniać rzeczy prywatnie w Internecie, osoby, którym udostępniasz dane, muszą mieć konta na serwerze, na którym znajdują się Twoje dane; w przeciwnym razie serwer nie może uwierzytelniać odwiedzających witrynę, aby wiedzieć, czy przyznać im dostęp. $Projectname rozwiązuje ten problem za pomocą zaawansowanego systemu zdalnego uwierzytelniania, który weryfikuje tożsamość odwiedzających, wykorzystując techniki obejmujące kryptografię klucza publicznego.
|
||||
Chociaż wszystkie te aplikacje i usługi można znaleźć w innych pakietach oprogramowania, tylko $Projectname pozwala ustawić uprawnienia dla grup i osób, [b]które mogą nawet nie mieć kont na Twoim węźle[/b]! W typowych aplikacjach internetowych, jeśli chcesz udostępniać rzeczy prywatnie w Internecie, osoby, którym udostępniasz dane, muszą mieć konta na serwerze, na którym znajdują się Twoje dane; w przeciwnym razie serwer nie może uwierzytelniać odwiedzających witrynę, aby wiedzieć, czy przyznać im dostęp. $Projectname rozwiązuje ten problem za pomocą zaawansowanego systemu zdalnego uwierzytelniania, który weryfikuje tożsamość odwiedzających, wykorzystując techniki obejmujące kryptografię klucza publicznego.
|
||||
Dzięki oferowanym aplikacjom, $Projectname świetnie się nadaje do budowy platformy komunikacyjno-publikacyjnej o charkterze społecznościowym dla realnych grup społecznych, takich jak rodziny, lokalne grupy, organizacje społeczne, środowiska szkolne, wspólnoty mieszkańców czy wspólnoty religijne.
|
||||
|
||||
[h3]Stos programów[/h3]
|
||||
Pakiet oprogramowania $Projectname jest stosunkowo standardową aplikacją serwerową napisaną głównie w PHP i MySQL i [url=https://framagit.org/$Projectname/core/blob/master/install/INSTALL.txt]wymagającą niewiele więcej niż serwera WWW, bazy danych zgodnej z MySQL i języka skryptowego PHP[/url]. System został zaprojektowany tak, aby był łatwy do zainstalowania przez osoby z podstawowymi umiejętnościami administrowania witryną, na typowych platformach współdzielonego hostingu, z uwzglednieniem szerokiej gamy sprzętu komputerowego. Można go również łatwo rozszerzyć za pomocą wtyczek i motywów oraz innych narzędzi innych firm.
|
||||
Pakiet oprogramowania $Projectname jest stosunkowo standardową aplikacją serwerową napisaną głównie w PHP i MySQL,
|
||||
[url=https://framagit.org/$Projectname/core/blob/master/install/INSTALL.txt]wymagającą niewiele więcej niż serwera WWW,
|
||||
bazy danych zgodnej z MySQL i środowiska wykonawczego PHP[/url]. System został zaprojektowany tak, aby był łatwy do
|
||||
zainstalowania przez osoby z podstawowymi umiejętnościami administrowania witryną, na typowych platformach współdzielonego
|
||||
hostingu, z uwzglednieniem szerokiej gamy sprzętu komputerowego. Można go również łatwo rozszerzyć za pomocą wtyczek i motywów
|
||||
oraz innych narzędzi zewnętrznych.
|
||||
|
||||
[h3]Słownik[/h3]
|
||||
[dl terms="b"]
|
||||
[*= hub ([i]ang. hub[/i])] Instancja tego oprogramowania działająca na standardowym serwerze WWW
|
||||
[*= węzeł ([i]ang. hub[/i])] Instancja oprogramowania $Projectname działająca na standardowym serwerze WWW
|
||||
|
||||
[*= siatka, grid ([i]w oryginale ang., grid[/i])] Globalna sieć hubów, które wymieniają między sobą informacje za pomocą protokołu Zot. Nie są to tylko huby oparte na $Projectname, ale wszystkie hubyy implementujace protokół Zot.
|
||||
[*= sieć Zot, sieć ([i]w oryginale ang., grid[/i])] Globalna sieć węzłów, które wymieniają między sobą informacje za pomocą protokołu Zot. Nie są to tylko węzły oparte na $Projectname, ale wszystkie węzły implementujace protokół Zot.
|
||||
|
||||
[*= kanał ([i]ang. channel[/i])] Techniczny odpowiednik tożsamości. Kanał może reprezentować osobę, blog lub forum, żeby wymienić tylko kilka. Kanały mogą łączyć się z innymi kanałami w celu udostępniania informacji z bardzo szczegółowymi uprawnieniami.
|
||||
[*= kanał ([i]ang. channel[/i])] Forma organizacji treści i techniczny odpowiednik tożsamości. Kanał może mieć formę osobistej witryny internetowej, bloga, forum i innych znanych form publikowania treści. Kanały mogą łączyć się z innymi kanałami w celu udostępniania informacji z możliwością ustawiania bardzo szczegółowych uprawnień dostępu.
|
||||
|
||||
[*= klon ([i]ang. clone[/i])] Kanały mogą mieć klony powiązane z oddzielnymi i niepowiązanymi kontami w niezależnych hubach. Komunikacja współdzielona z kanałem jest synchronizowana między klonami kanału, co umożliwia kanałowi wysyłanie i odbieranie wiadomości oraz dostęp do współdzielonych treści z wielu hubów. Zapewnia to odporność na awarie sieci i sprzętu, które mogą stanowić poważny problem w przypadku serwerów WWW z własnym hostingiem lub o ograniczonych zasobach. Klonowanie umożliwia całkowite przeniesienie kanału z jednego huba do drugiego, zabierając ze sobą dane i połączenia. Zobacz "tożsamość nomadyczna".
|
||||
[*= klon ([i]ang. clone[/i])] Kanały mogą mieć klony innych na innych niezależnych węzłach. Komunikacja współdzielona z kanałem jest synchronizowana między klonami kanału, co umożliwia kanałowi wysyłanie i odbieranie wiadomości oraz dostęp do współdzielonych treści z wielu węzłów. Zapewnia to odporność na awarie sieci i sprzętu, które mogą stanowić poważny problem w przypadku serwerów WWW utrzymywanych na prywatnych serwerach w hostingu współdzielonym lub o ograniczonych zasobach. Klonowanie umożliwia też całkowite przeniesienie kanału z jednego węzła na drugi, z zabraniem wszystkich danych i połączeń. Zobacz "tożsamość nomadyczna".
|
||||
|
||||
[*= tożsamość nomadyczna ([i]ang. nomadic identity[/i])] Możliwość uwierzytelniania i łatwej migracji tożsamości w niezależnych hubach i domenach internetowych. Tożsamość nomadyczna zapewnia prawdziwą własność tożsamości online, ponieważ tożsamości kanałów kontrolowanych przez konto w hubie nie są powiązane z samym hubem. hub bardziej przypomina "hosta" kanałów. W serwisie $Projectname nie masz "konta" na serwerze, tak jak na typowych serwisach internetowych - posiadasz tożsamość, którą możesz przenosić ze sobą po całej siatce za pomocą klonów.
|
||||
[*= konto ([i]ang. account[/i])] Umowny rejestr zawierajacy dane rejestracyjne i ewentualnie inne dane użytkownika serwisu internetowego, ściśle związane z umową jaką zwiera użytkownik z operatorem (właścicielem) serwisu o świadczenie usług drogą internetową. Posiadanie konta umożliwia użytkownikowi korzystanie z usług serwisu. Nie jest to pojęcie specyficzne dla platformy Hubzilla ale ma tu znaczenie węższe i należy go odróżniać od profilu lub tożsamości użytkownika. W Hubzilla, użytkownik (w ramach swojego konta) może mieć wiele tożsamości i te tożsamości utrzymywać na wielu odrębnych serwisach w sieci Zotm, w sposób zsynchronizowany. Na tych serwisach użytkownik musi mieć odrębne konta.
|
||||
|
||||
[*= tożsamość nomadyczna ([i]ang. nomadic identity[/i])] Możliwość uwierzytelniania i łatwej migracji tożsamości pomiędzy niezależnymi węzłami i domenami internetowymi. Tożsamość nomadyczna zapewnia prawdziwą własność tożsamości internetową, ponieważ tożsamości kontrolowane przez konto w węźle nie są ściśle związane z węzłem. Węzeł bardziej przypomina "hosta" kanałów. W serwisie $Projectname nie masz "konta" na serwerze, tak jak na typowych serwisach internetowych - posiadasz tożsamość, którą możesz przenosić w całej sieci za pomocą mechanizmu klonowania.
|
||||
|
||||
[*= [url=[baseurl]/help/developer/zot_protocol]Protokół Zot[/url]] Nowy protokół, oparty na JSON, do wdrażania bezpiecznej, zdecentralizowanej komunikacji i usług. Różni się od wielu innych protokołów komunikacyjnych, budując komunikację na podstawie zdecentralizowanej struktury tożsamości i uwierzytelniania. Składnik uwierzytelniania jest koncepcyjnie podobny do OpenID, ale jest odizolowany od tożsamości opartej na DNS. Tam, gdzie to możliwe, zdalne uwierzytelnianie jest ciche i niewidoczne. Zapewnia to mechanizm kontroli dostępu rozproszonego na skalę sieci WWW, który jest dyskretny.
|
||||
[/dl]
|
||||
@@ -43,14 +54,14 @@ Gdy to zrobisz, narzędzie "Suwak zaprzyjaźnienia", które zwykle pojawia się
|
||||
Suwak zaprzyjażnienia umożliwia natychmiastowe filtrowanie dużych ilości treści, pogrupowanych według poziomów zaprzyjaźnienia.
|
||||
|
||||
[h4]Filtrowanie połączeń (Connection Filtering)[/h4]
|
||||
Masz możliwość precyzyjnego kontrolowania tego, co pojawia się w Twoim strumieniu za pomocą opcjonalnego "Filtra połączeń" ([i]ang. Connection Filter[/i]). Po włączeniu Edytor połączeń zapewnia dane wejściowe do wybierania kryteriów, które należy dopasować, aby uwzględnić lub wykluczyć określony post z określonego kanału. Gdy post został dopuszczony, wszystkie komentarze do tego posta są dozwolone, niezależnie od tego, czy spełniają kryteria wyboru. Możesz wybrać słowa, które jeśli są obecne, blokują post lub zapewniają, że zostanie uwzględniony w Twoim strumieniu. Wyrażenia regularne mogą być używane do jeszcze dokładniejszej kontroli, a także hasztagów, a nawet wykrytego języka postu.
|
||||
Masz możliwość precyzyjnego kontrolowania tego, co pojawia się w Twoim strumieniu za pomocą opcjonalnego "Filtra połączeń" ([i]ang. Connection Filter[/i]). Po włączeniu Edytor połączeń zapewnia dane wejściowe do wybierania kryteriów, które należy dopasować, aby uwzględnić lub wykluczyć określony wpis z określonego kanału. Gdy wpis został dopuszczony, wszystkie komentarze do tego wpisu są dozwolone, niezależnie od tego, czy spełniają kryteria wyboru. Możesz wybrać słowa, które jeśli są obecne, blokują wpis lub zapewniają, że zostanie uwzględniony w Twoim strumieniu. Wyrażenia regularne mogą być używane do jeszcze dokładniejszej kontroli, a także hasztagów, a nawet wykrytego języka wpisu.
|
||||
|
||||
[h4]Listy kontrolne dostępu (Access Control Lists - ACL)[/h4]
|
||||
Udostępniając zawartość, członkowie mają możliwość ograniczenia tego, kto widzi zawartość. Klikając na kłódkę pod polem udostępniania, można wybrać odbiorców postu, klikając ich nazwy.
|
||||
Udostępniając zawartość, członkowie mają możliwość ograniczenia tego, kto widzi zawartość. Klikając na kłódkę pod polem udostępniania, można wybrać odbiorców wpisu, klikając ich nazwy.
|
||||
|
||||
Po wysłaniu, wiadomość będzie widoczna tylko dla nadawcy i wybranych odbiorców. Innymi słowami, wiadomość nie pojawi się na jakichkolwiek publicznych ścianach.
|
||||
|
||||
Listy kontroli dostępu mogą być stosowane do treści i postów, zdjęć, wydarzeń, stron internetowych, pokojów rozmów i plików.
|
||||
Listy kontroli dostępu mogą być stosowane do treści i wpisów, zdjęć, wydarzeń, stron internetowych, pokojów rozmów i plików.
|
||||
|
||||
[h4]Jednokrotne uwierzytelnianie (Single Sign-on)[/h4]
|
||||
Listy kontroli dostępu działają dla wszystkich kanałów w siatce dzięki naszej unikalnej technologii pojedynczego logowania. Większość linków wewnętrznych zapewnia token tożsamości, który można zweryfikować w innych witrynach $Projectname i wykorzystać do kontrolowania dostępu do prywatnych zasobów. Logujesz się raz do swojego centrum domowego. Następnie uwierzytelnianie we wszystkich zasobach serwisu $Projectname jest "magiczne".
|
||||
@@ -62,7 +73,7 @@ Pliki można przesyłać do osobistego obszaru przechowywania za pomocą narzęd
|
||||
Przechowuj zdjęcia w albumach. Wszystkie Twoje zdjęcia mogą być chronione listami kontroli dostępu.
|
||||
|
||||
[h4]Kalendarze zdarzeń[/h4]
|
||||
Twórz zdarzenia i zadania oraz zarządzaj nimi, które mogą być również chronione za pomocą list kontroli dostępu. Wydarzenia można importować i eksportować do innego oprogramowania przy użyciu standardowego formatu vcalendar lub iCal i udostępniać w postach innym osobom. Wydarzenia urodzinowe są automatycznie dodawane od znajomych i konwertowane na właściwą strefę czasową, dzięki czemu będziesz dokładnie wiedzieć, kiedy mają miejsce urodziny - bez względu na to, gdzie się znajdujesz na świecie w stosunku do osoby urodzonej w dniu urodzin. Wydarzenia są zwykle tworzone za pomocą liczników obecności, dzięki czemu Twoi znajomi i kontakty mogą natychmiast [url=https://pl.wikipedia.org/wiki/RSVP_(skr%C3%B3towiec]RSVP[/url].
|
||||
Twórz zdarzenia i zadania oraz zarządzaj nimi, które mogą być również chronione za pomocą list kontroli dostępu. Wydarzenia można importować i eksportować do innego oprogramowania przy użyciu standardowego formatu vcalendar lub iCal i udostępniać w wpisuch innym osobom. Wydarzenia urodzinowe są automatycznie dodawane od znajomych i konwertowane na właściwą strefę czasową, dzięki czemu będziesz dokładnie wiedzieć, kiedy mają miejsce urodziny - bez względu na to, gdzie się znajdujesz na świecie w stosunku do osoby urodzonej w dniu urodzin. Wydarzenia są zwykle tworzone za pomocą liczników obecności, dzięki czemu Twoi znajomi i kontakty mogą natychmiast [url=https://pl.wikipedia.org/wiki/RSVP_(skr%C3%B3towiec]RSVP[/url].
|
||||
|
||||
[h4]Czaty[/h4]
|
||||
Możesz utworzyć dowolną liczbę osobistych czatów i zezwolić na dostęp za pośrednictwem list kontroli dostępu. Są one zazwyczaj bezpieczniejsze niż XMPP, IRC i inne rodzaje przesyłania wiadomości błyskawicznych, chociaż zezwalamy również na korzystanie z tych innych usług za pośrednictwem wtyczek.
|
||||
@@ -82,7 +93,7 @@ Udostępniaj i zapisuj albo zarządzaj zakładkami z linków podanych na czacie.
|
||||
[h4]Szyfrowanie wiadomości prywatnych i kwestie prywatności[/h4]
|
||||
Prywatna poczta jest przechowywana w ukrytym formacie. Chociaż nie jest to "kuloodporne", zwykle zapobiega przypadkowemu podsłuchiwaniu przez administratora witryny lub usługodawcę internetowego.
|
||||
|
||||
Każdy kanał serwisu $Projectname ma swój własny unikalny zestaw prywatnych i powiązanych publicznych kluczy RSA 4096-bitowych, generowanych podczas pierwszego tworzenia kanałów. Służy do ochrony przesyłanych prywatnych wiadomości i postów.
|
||||
Każdy kanał serwisu $Projectname ma swój własny unikalny zestaw prywatnych i powiązanych publicznych kluczy RSA 4096-bitowych, generowanych podczas pierwszego tworzenia kanałów. Służy do ochrony przesyłanych prywatnych wiadomości i wpisów.
|
||||
|
||||
Ponadto wiadomości mogą być tworzone przy użyciu "szyfrowania end-to-end", którego nie mogą odczytać operatorzy serwisów $Projectname, dostawcy usług internetowych ani nikt, kto nie zna hasła.
|
||||
|
||||
@@ -90,24 +101,24 @@ Wiadomości publiczne na ogół nie są szyfrowane podczas przesyłania ani prze
|
||||
|
||||
Prywatne wiadomości mogą zostać wycofane po wysłaniu, chociaż nie ma gwarancji, że odbiorca ich jeszcze nie przeczytał.
|
||||
|
||||
Posty i wiadomości mogą być tworzone z datą wygaśnięcia, po którym zostaną usunięte lub usunięte ze strony odbiorcy.
|
||||
Wpisy i wiadomości mogą być tworzone z datą wygaśnięcia, po którym zostaną usunięte lub usunięte ze strony odbiorcy.
|
||||
|
||||
[h4]Federalizacja usług (Service Federation)[/h4]
|
||||
Oprócz dodatkowych "łączników cross-post" do różnych alternatywnych sieci, istnieje natywna obsługa importu treści z kanałów RSS i Atom i wykorzystywania jej do tworzenia specjalnych kanałów. Dostępne są również wtyczki do komunikacji z innymi sieciami za pomocą protokołów Diaspora i GNU-Social (OStatus). Sieci te nie obsługują tożsamości nomadycznej ani kontroli dostępu między domenami. Jednak podstawowa komunikacja jest obsługiwana: do i z Diaspora, Friendica, GNU-Social, Mastodon i innych dostawców, którzy używają tych protokołów.
|
||||
Oprócz dodatkowych łączników między wpisami z różnych alternatywnych sieci, istnieje natywna obsługa importu treści z kanałów RSS i Atom i wykorzystywania jej do tworzenia specjalnych kanałów. Dostępne są również wtyczki do komunikacji z innymi sieciami za pomocą protokołów Diaspora i GNU-Social (OStatus). Sieci te nie obsługują tożsamości nomadycznej ani kontroli dostępu między domenami. Jednak podstawowa komunikacja jest obsługiwana: do i z Diaspora, Friendica, GNU-Social, Mastodon i innych dostawców, którzy używają tych protokołów.
|
||||
|
||||
Istnieje również eksperymentalna obsługa uwierzytelniania OpenID, której można używać na listach kontroli dostępu. To jest jeszcze w trakcie tworzenia, ale poeksperymentować można. Twój hub $Projectname może być używany jako dostawca OpenID do uwierzytelniania członków w zewnętrznych usługach korzystających z tej technologii.
|
||||
Istnieje również eksperymentalna obsługa uwierzytelniania OpenID, której można używać na listach kontroli dostępu. To jest jeszcze w trakcie tworzenia, ale poeksperymentować można. Twój węzeł $Projectname może być używany jako dostawca OpenID do uwierzytelniania członków w zewnętrznych usługach korzystających z tej technologii.
|
||||
|
||||
Kanały mogą mieć uprawnienia, aby stać się "kanałami pochodnymi", w przypadku gdy dwa lub więcej istniejących kanałów łączy się, tworząc nowy kanał tematyczny.
|
||||
|
||||
[h4]Grupy prywatności (Privacy Group)[/h4]
|
||||
Nasza implementacja grup prywatności jest podobna do "kręgów" w Google i "aspektów" w Diasporze. Pozwala to na filtrowanie przychodzącego strumienia według wybranych grup i automatyczne ustawianie wychodzącej listy kontroli dostępu tylko na te z tej grupy prywatności podczas publikowania. Możesz to zmienić w dowolnym momencie (przed wysłaniem postu).
|
||||
Nasza implementacja grup prywatności jest podobna do "kręgów" w Google i "aspektów" w Diasporze. Pozwala to na filtrowanie przychodzącego strumienia według wybranych grup i automatyczne ustawianie wychodzącej listy kontroli dostępu tylko na te z tej grupy prywatności podczas publikowania. Możesz to zmienić w dowolnym momencie (przed wysłaniem wpisu).
|
||||
|
||||
|
||||
[h4]Usługi katalogowe (Directory Services)[/h4]
|
||||
Zapewniamy łatwy dostęp do katalogu członków i udostępniamy zdecentralizowane narzędzia, które mogą dostarczać "sugestie" znajomych. Katalogi to zwykłe serwisy $Projectname, które zdecydowały się zaakceptować rolę serwera katalogowego. Wymaga to więcej zasobów niż większość typowych serwisów, więc nie jest to ustawienie domyślne. Katalogi są synchronizowane i dublowane, dzięki czemu wszystkie zawierają aktualne informacje o całej sieci (z zastrzeżeniem normalnych opóźnień propagacji).
|
||||
Zapewniamy łatwy dostęp do katalogu członków i udostępniamy zdecentralizowane narzędzia, które mogą dostarczać "sugestie" znajomych. Katalogi to zwykłe serwisy $Projectname, które zdecydowały się zaakceptować rolę serwera katalogowego. Wymaga to więcej zasobów niż większość typowych serwisów, więc nie jest to ustawienie domyślne. Katalogi są synchronizowane i dublowane, dzięki czemu wszystkie zawierają aktualne informacje o całej sieci (z zastrzeżeniem normalnych opóźnień propagacji). Więcej na ten temat znajdziesz w artykule [Konfiguracja katalogu](/help/pl/directories).
|
||||
|
||||
[h4]TLS/SSL[/h4]
|
||||
W przypadku hubów $Projectname, które używają TLS/SSL, komunikacja między klientem a serwerem jest szyfrowana za pomocą protokołu TLS/SSL. Biorąc pod uwagę niedawno ujawnione w mediach fakty dotyczące powszechnego, globalnego nadzoru i obchodzenia szyfrowania przez NSA i GCHQ, uzasadnione jest założenie, że komunikacja chroniona przez HTTPS może być zagrożona na różne sposoby. W konsekwencji prywatna komunikacja jest szyfrowana na wyższym poziomie przed wysłaniem na zewnątrz.
|
||||
W przypadku węzłów $Projectname, które używają TLS/SSL, komunikacja między klientem a serwerem jest szyfrowana za pomocą protokołu TLS/SSL. Biorąc pod uwagę niedawno ujawnione w mediach fakty dotyczące powszechnego, globalnego nadzoru i obchodzenia szyfrowania przez NSA i GCHQ, uzasadnione jest założenie, że komunikacja chroniona przez HTTPS może być zagrożona na różne sposoby. W konsekwencji prywatna komunikacja jest szyfrowana na wyższym poziomie przed wysłaniem na zewnątrz.
|
||||
|
||||
[h4]Konfiguracja kanałów[/h4]
|
||||
Podczas tworzenia kanału wybierana jest rola, która stosuje szereg wstępnie skonfigurowanych ustawień zabezpieczeń i prywatności. Są one wybierane z uwzględnieniem najlepszych praktyk, aby zachować prywatność na żądanym poziomie.
|
||||
@@ -124,27 +135,27 @@ W przypadku wybrania "własnej" roli prywatności każdy kanał umożliwia precy
|
||||
|
||||
|
||||
[h4]Prywatne i publiczne fora[/h4]
|
||||
Fora to zazwyczaj kanały, w których może uczestniczyć wielu autorów. Obecnie istnieją dwa mechanizmy publikowania postów na forach:
|
||||
Fora to zazwyczaj kanały, w których może uczestniczyć wielu autorów. Obecnie istnieją dwa mechanizmy publikowania wpisów na forach:
|
||||
|
||||
- posty "wall-to-wall" i
|
||||
- wpisy na całą ścianę (ang. wall-to-wall) i
|
||||
- mechanizm tagów forowych @mention.
|
||||
|
||||
Fora mogą być tworzone przez każdego i używane w dowolnym celu. Katalog zawiera opcję wyszukiwania forów publicznych. Fora prywatne mogą być publikowane tylko dla członków i często tylko przez nich widoczne.
|
||||
|
||||
[h4]Klonowanie kont[/h4]
|
||||
Konta platformy $Projectname nazywane są *tożsamościami nomadycznymi*, ponieważ tożsamość członka nie jest powiązana z hubem, w którym tożsamość została pierwotnie utworzona. Na przykład, kiedy tworzysz konto na Facebooku lub Gmailu, jest ono powiązane z tymi usługami - mie może działać poza Facebook.com czy Gmail.com.
|
||||
[h4]Klonowanie tożsamości[/h4]
|
||||
Kanały platformy $Projectname nazywane są [i]tożsamościami nomadycznymi[/i], ponieważ tożsamość członka (jego profil i związany z nim kanał) nie jest powiązana z węzłem, w którym tożsamość została pierwotnie utworzona. Na przykład, kiedy tworzysz konto na Facebooku lub Gmailu, jest ono ściśle powiązane z tymi usługami - mie możesz używać tych usług poza Facebook.com czy Gmail.com. Z drugiej strony załóżmy, że masz konto na serwisie Hubzillahub.com i w ramach tego konta utworzyłeś kanał o nazwie [code]jacek@Hubzillahub.com[/code]. Możesz sklonować go do innego węzła Hubzilla, wybierając tę samą lub inną nazwę, np. [code]blogJacka@SomeHubzillahub.info[/code].
|
||||
|
||||
Z drugiej strony załóżmy, że utworzyłeś tożsamość $Projectname o nazwie [code]tina@$Projectnamehub.com[/code]. Możesz sklonować ją do innego huba $Projectname, wybierając tę samą lub inną nazwę, np. [code]liveForever@Some$ProjectnameHub.info[/code].
|
||||
Z drugiej strony załóżmy, że utworzyłeś tożsamość $Projectname o nazwie [code]tina@$Projectnamehub.com[/code]. Możesz sklonować ją do innego węzła $Projectname, wybierając tę samą lub inną nazwę, np. [code]liveForever@Some$ProjectnameHub.info[/code].
|
||||
|
||||
Oba kanały są teraz zsynchronizowane, co oznacza, że wszystkie Twoje kontakty i preferencje zostaną zduplikowane na klonie. Nie ma znaczenia, czy wyślesz post z pierwotnego centrum, czy z nowego. Posty będą dublowane na obu kontach.
|
||||
Oba kanały są teraz zsynchronizowane, co oznacza, że wszystkie Twoje kontakty i preferencje zostaną zduplikowane na klonie. Nie ma znaczenia, czy wyślesz wpis z pierwotnego centrum, czy z nowego. Wpisy będą dublowane na obu kontach.
|
||||
|
||||
To dość rewolucyjna funkcja, jeśli weźmiemy pod uwagę kilka scenariuszy:
|
||||
|
||||
- Co się stanie, jeśli hub, w którym oparta jest tożsamość, nagle przestanie działać? Bez sklonowania tożsamości członek tego huba nie będzie mógł się komunikować, dopóki hub nie wróci do trybu online (bez wątpienia wielu z Was widziało i przeklęło "Fail Whale" na Twitterze). Dzięki klonowaniu wystarczy zalogować się na sklonowane konto, a życie toczy się normalnie.
|
||||
- Co się stanie, jeśli węzeł, na którym oparta jest tożsamość, nagle przestanie działać? Bez sklonowania tożsamości członek tego węzła nie będzie mógł się komunikować, dopóki węzeł nie wróci do trybu online (bez wątpienia wielu z Was widziało i przeklęło "Fail Whale" na Twitterze). Dzięki klonowaniu wystarczy zalogować się na sklonowane konto, a życie toczy się normalnie.
|
||||
|
||||
- Administrator twojego huba nie może już sobie pozwolić na opłacanie swojego bezpłatnego i publicznego huba $Projectname. Zapowiada, że hub zostanie zamknięty za dwa tygodnie. Dzięki temu masz wystarczająco dużo czasu na sklonowanie swojej tożsamośc i zachowanie relacji, znajomych i treści z zamykanego serwisu $Projectname.
|
||||
- Administrator twojego węzła nie może już sobie pozwolić na opłacanie swojego bezpłatnego i publicznego węzła $Projectname. Zapowiada, że węzeł zostanie zamknięty za dwa tygodnie. Dzięki temu masz wystarczająco dużo czasu na sklonowanie swojej tożsamośc i zachowanie relacji, znajomych i treści z zamykanego serwisu $Projectname.
|
||||
|
||||
- A jeśli Twoja tożsamość podlega rządowej cenzurze? Twój dostawca huba może zostać zmuszony do usunięcia Twojego konta wraz z wszelkimi tożsamościami i powiązanymi danymi. Dzięki klonowaniu, $Projectname stawia opór cenzurze. Możesz mieć setki klonów, jeśli chcesz, wszystkie nazwane inaczej i istniejące w wielu różnych hubach, rozrzuconych po Internecie.
|
||||
- A jeśli Twoja tożsamość podlega rządowej cenzurze? Twój dostawca węzła może zostać zmuszony do usunięcia Twojego konta wraz z wszelkimi tożsamościami i powiązanymi danymi. Dzięki klonowaniu, $Projectname stawia opór cenzurze. Możesz mieć setki klonów, jeśli chcesz, wszystkie nazwane inaczej i istniejące w wielu różnych węzłach, rozrzuconych po Internecie.
|
||||
|
||||
$Projectname oferuje interesujące nowe możliwości prywatności. Więcej informacji można znaleźć na stronie "Najlepsze praktyki w komunikacji prywatnej".
|
||||
Obowiązują pewne zastrzeżenia. Aby uzyskać pełne wyjaśnienie klonowania tożsamości, przeczytaj stronę "JAK SKLONOWAĆ SWOJĄ TOŻSAMOŚĆ".
|
||||
@@ -157,19 +168,19 @@ Można utworzyć dowolną liczbę profili zawierających różne informacje, kt
|
||||
$Projectname oferuje prosty sposób wykonywania kopii zapasowej konta za jednym kliknięciem, z której możesz pobrać pełną kopię zapasową swoich profili. Kopie zapasowe można następnie wykorzystać do sklonowania lub przywrócenia profilu.
|
||||
|
||||
[h4]Usuwanie konta[/h4]
|
||||
Konta można natychmiast usunąć, klikając link. Otóż to. Wszystkie powiązane treści są następnie usuwane z siatki (w tym posty i wszelkie inne treści utworzone przez usunięty profil). W zależności od liczby posiadanych połączeń proces usuwania zdalnej zawartości może zająć trochę czasu, ale zaplanowany jest tak szybko, jak to możliwe.
|
||||
Konta można natychmiast usunąć, klikając link. Otóż to. Wszystkie powiązane treści są następnie usuwane z sieci (w tym wpisy i wszelkie inne treści utworzone przez usunięty profil). W zależności od liczby posiadanych połączeń proces usuwania zdalnej zawartości może zająć trochę czasu, ale zaplanowany jest tak szybko, jak to możliwe.
|
||||
|
||||
[h4]Usuwanie treści[/h4]
|
||||
Wszelkie treści utworzone w Hubzilli pozostają pod kontrolą członka (lub kanału), który je pierwotnie utworzył. W dowolnym momencie członek może usunąć wiadomość lub zakres wiadomości. Proces usuwania zapewnia, że treść zostanie usunięta, niezależnie od tego, czy została opublikowana w głównym (macierzystym) hubie kanału, czy w innym hubie, gdzie kanał został zdalnie uwierzytelniony za pośrednictwem Zot (protokół komunikacji i uwierzytelniania $Projectname).
|
||||
Wszelkie treści utworzone w Hubzilli pozostają pod kontrolą członka (lub kanału), który je pierwotnie utworzył. W dowolnym momencie członek może usunąć wiadomość lub zakres wiadomości. Proces usuwania zapewnia, że treść zostanie usunięta, niezależnie od tego, czy została opublikowana w głównym (macierzystym) węźle kanału, czy w innym węźle, gdzie kanał został zdalnie uwierzytelniony za pośrednictwem Zot (protokół komunikacji i uwierzytelniania $Projectname).
|
||||
|
||||
[h4]Media[/h4]
|
||||
Podobnie jak każdy inny nowoczesny system blogowania, sieć społecznościowa lub usługa mikroblogowania, $Projectname obsługuje przesyłanie plików, osadzanie filmów, łączenie stron internetowych.
|
||||
|
||||
[h4]Podgląd i edycja[/h4]
|
||||
Posty i komentarze można przeglądać przed wysłaniem i edytować po wysłaniu.
|
||||
Wpisy i komentarze można przeglądać przed wysłaniem i edytować po wysłaniu.
|
||||
|
||||
[h4]Głosowanie i konsensus[/h4]
|
||||
Posty mogą być przekształcane w elementy "konsensusu", które pozwalają czytelnikom oferować opinie, które są zestawiane w liczniki "zgadzam się", "nie zgadzam się" i "wstrzymuję się". Pozwala to ocenić zainteresowanie pomysłami i tworzyć nieformalne ankiety.
|
||||
Wpisy mogą być przekształcane w elementy "konsensusu", które pozwalają czytelnikom oferować opinie, które są zestawiane w liczniki "zgadzam się", "nie zgadzam się" i "wstrzymuję się". Pozwala to ocenić zainteresowanie pomysłami i tworzyć nieformalne ankiety.
|
||||
|
||||
[h4]Rozszerzaie $Projectname[/h4]
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
[h3]Zarządzanie projektem $Projectname[/h3]
|
||||
Zarządzanie $Projectname odnosi się do zarządzania tym projektem i zwłaszcza jak do rozwiązywania konfliktów w tym projekcie.
|
||||
Zarządzanie $Projectname odnosi się do zarządzania tym projektem a zwłaszcza do tego jak rozwiązywane są konflikty w tym projekcie.
|
||||
|
||||
[h4]Zarządzanie społecznością[/h4]
|
||||
Projekt jest utrzymywany przez społeczność $Projectname i decyzje podejmowane są w ramach tej społeczności.
|
||||
Struktura zarządzania ciągle ewoluuje. Do czasu zakończenia tworzenia struktura, decyzje są podejmowane w następującej kolejności:
|
||||
Projekt jest utrzymywany przez społeczność $Projectname i decyzje podejmowane są w ramach tej społeczności. Struktura zarządzania ciągle się rozwija. Do czasu zakończenia tworzenia tej struktury, decyzje są podejmowane w następującej kolejności:
|
||||
|
||||
[ol]
|
||||
[*] Opóźniony konsensus
|
||||
@@ -13,7 +12,7 @@ Jeśli propozycja projektu zostanie złożona na jednym z forów zarządzania pr
|
||||
|
||||
[*] Weto
|
||||
|
||||
Starsi deweloperzy, z długim stażem w projekcie. mogą zawetować każdą decyzję. Decyzja może zostać podjęta dopiero po usunięciu weta lub przedłożeniu alternatywnej propozycji.
|
||||
Starsi deweloperzy, z długim stażem w projekcie, mogą zawetować każdą decyzję. Decyzja może zostać podjęta dopiero po usunięciu weta lub przedłożeniu alternatywnej propozycji.
|
||||
|
||||
|
||||
[*] Głosowanie społeczności
|
||||
@@ -27,25 +26,25 @@ Głosowanie społeczności nie zawsze zapewnia Powszechnie akceptowany wynik i m
|
||||
|
||||
Q: Kto może widzieć moją treść?
|
||||
|
||||
A: Domyślnie KAŻDY w internecie, chyba że ograniczysz do niej dostęp. $Projectname pozwala wybrać żądany poziom prywatności. Treści podlegające ograniczeniom NIE będą widoczne dla "sieci szpiegowskich" i reklamodawców. Będą chroniona przed podsłuchem przez osoby postronne - najlepiej jak potrafimy. Administratorzy centrów z wystarczającymi umiejętnościami i cierpliwością MOGĄ być w stanie podsłuchiwać niektóre prywatne wiadomości, ale muszą dołożyć starań, aby to zrobić. W $Projectname istnieją tryby prywatności, które są nawet odporne na podsłuchiwanie przez wykwalifikowanych i zdeterminowanych administratorów hubów.
|
||||
A: Domyślnie KAŻDY w Internecie, chyba że ograniczysz do niej dostęp. $Projectname pozwala wybrać żądany poziom prywatności. Treści podlegające ograniczeniom NIE będą widoczne dla "sieci szpiegowskich" i reklamodawców. Będą chroniona przed podsłuchem przez osoby wpisronne - najlepiej jak potrafimy. Administratorzy centrów z wystarczającymi umiejętnościami i cierpliwością MOGĄ być w stanie podsłuchiwać niektóre prywatne wiadomości, ale muszą dołożyć starań, aby to zrobić. W $Projectname istnieją tryby prywatności, które są nawet odporne na podsłuchiwanie przez wykwalifikowanych i zdeterminowanych administratorów węzłów.
|
||||
|
||||
Q: Czy moje treści mogą zostać ocenzurowane?
|
||||
|
||||
A: Z założenie, $Projectname (jako sieć) NIE MOŻE cenzurować twoich treści. Administratorzy serwerów i hubów podlegają lokalnemu prawodawstwu i MOGĄ usunąć budzące zastrzeżenia treści ze swojego serwisu (huba). Każdy może zostać administratorem huba, w tym Ty. Dlatego publikuj treści, które w innym przypadku mogłyby zostać ocenzurowane. Nadal MOŻESZ podlegać lokalnemu prawodawstwu.
|
||||
A: Z założenie, $Projectname (jako sieć) NIE MOŻE cenzurować twoich treści. Administratorzy serwerów i węzłów podlegają lokalnemu prawodawstwu i MOGĄ usunąć budzące zastrzeżenia treści ze swojego serwisu (węzła). Każdy może zostać administratorem węzła, w tym Ty. Dlatego publikuj treści, które w innym przypadku mogłyby zostać ocenzurowane. Nadal MOŻESZ podlegać lokalnemu prawodawstwu.
|
||||
|
||||
[h5]Definicje[/h5]
|
||||
|
||||
**$Projectname**
|
||||
|
||||
Inaczej nazywana "siecią", $Projectname jest zbiorem pojedynczych komputerów (serwerów) (czyli **hubów**. ang. *hubs*), które łączą się razem, tworząc większą sieć kooperacyjną.
|
||||
Inaczej nazywana "siecią", $Projectname jest zbiorem pojedynczych komputerów (serwerów) (czyli **węzłów**. ang. *hubs*), które łączą się razem, tworząc większą sieć kooperacyjną.
|
||||
|
||||
**hub** (ang. *hub*)
|
||||
**węzeł** (ang. *hub*)
|
||||
|
||||
Pojedynczy komputer lub serwer podłączony do $Projectname. Jest on dostarczany przez **administratora huba** i może być publiczny lub prywatny, płatnu lub bezpłatny.
|
||||
Pojedynczy komputer lub serwer podłączony do $Projectname. Jest on dostarczany przez **administratora węzła** i może być publiczny lub prywatny, płatnu lub bezpłatny.
|
||||
|
||||
*administrator huba**
|
||||
*administrator węzła**
|
||||
|
||||
Operator systemu pojedynczego huba.
|
||||
Operator systemu pojedynczego węzła.
|
||||
|
||||
[h5]Polityki[/h5]
|
||||
|
||||
@@ -55,41 +54,41 @@ Wszelkie informacje lub cokolwiek zamieszczone przez Ciebie w $Projectname MOŻE
|
||||
|
||||
Twoje zdjęcie profilowe, nazwa Twojego kanału i lokalizacja (adres URL lub adres sieciowy) Twojego kanału są widoczne dla każdego w internecie, a kontrola prywatności nie wpływa na wyświetlanie tych elementów.
|
||||
|
||||
MOŻESZ dodatkowo podać inne informacje profilowe. Wszelkie informacje, które podajesz w swoim „domyślnym” lub **publicznym profilu** MOGĄ zostać przesłane do innych hubów w $Projectname i dodatkowo MOGĄ zostać wyświetlone w katalogu kanałów. Możesz ograniczyć wyświetlanie tych informacji profilowych. Może być ograniczone tylko do członków twojego huba lub tylko połączeń (znajomych) lub innych ograniczonych grup widzów, zgodnie z twoim życzeniem. Jeśli chcesz, aby Twój profil był ograniczony, musisz ustawić odpowiednie ustawienia prywatności lub po prostu NIE podawać dodatkowych informacji.
|
||||
MOŻESZ dodatkowo podać inne informacje profilowe. Wszelkie informacje, które podajesz w swoim „domyślnym” lub **publicznym profilu** MOGĄ zostać przesłane do innych węzłów w $Projectname i dodatkowo MOGĄ zostać wyświetlone w katalogu kanałów. Możesz ograniczyć wyświetlanie tych informacji profilowych. Może być ograniczone tylko do członków twojego węzła lub tylko połączeń (znajomych) lub innych ograniczonych grup widzów, zgodnie z twoim życzeniem. Jeśli chcesz, aby Twój profil był ograniczony, musisz ustawić odpowiednie ustawienia prywatności lub po prostu NIE podawać dodatkowych informacji.
|
||||
|
||||
**Treść**
|
||||
|
||||
Treści, które udostępniasz (posty ze statusami, zdjęcia, pliki itp.) Należą do Ciebie. $Projectname domyślnie publikuje treści w sposób otwarty i widoczny dla każdego w internecie (PUBLICZNY). MOŻESZ kontrolować to w ustawieniach swojego kanału i ograniczyć domyślne uprawnienia lub MOŻESZ ograniczyć widoczność każdego pojedynczego opublikowanego elementu oddzielnie (PRYWATNE). Programiści $Projectname zapewnią, że ograniczone treści będą widoczne TYLKO dla osób z listy ograniczeń - najlepiej jak potrafią.
|
||||
Treści, które udostępniasz (wpisy ze statusami, zdjęcia, pliki itp.) Należą do Ciebie. $Projectname domyślnie publikuje treści w sposób otwarty i widoczny dla każdego w internecie (PUBLICZNY). MOŻESZ kontrolować to w ustawieniach swojego kanału i ograniczyć domyślne uprawnienia lub MOŻESZ ograniczyć widoczność każdego pojedynczego opublikowanego elementu oddzielnie (PRYWATNE). Programiści $Projectname zapewnią, że ograniczone treści będą widoczne TYLKO dla osób z listy ograniczeń - najlepiej jak potrafią.
|
||||
|
||||
Treści (zwłaszcza posty statusowe), które udostępniasz innym sieciom lub które udostępniłeś komukolwiek w Internecie (PUBLICZNE), nie mogą być łatwo cofnięte po ich opublikowaniu. MOGĄ być udostępniane innym sieciom i udostępniane za pośrednictwem kanałów RSS / Atom. Może być również rozpowszechniany na innych stronach $ Projectname. MOŻE pojawiać się w innych sieciach i witrynach internetowych oraz być widoczny w wyszukiwarkach internetowych. Jeśli nie chcesz tego domyślnego zachowania, dostosuj ustawienia swojego kanału i ogranicz listę osób, które mogą oglądać Twoje treści.
|
||||
Treści (zwłaszcza wpisy statusowe), które udostępniasz innym sieciom lub które udostępniłeś komukolwiek w Internecie (PUBLICZNE), nie mogą być łatwo cofnięte po ich opublikowaniu. MOGĄ być udostępniane innym sieciom i udostępniane za pośrednictwem kanałów RSS / Atom. Może być również rozpowszechniany na innych stronach $ Projectname. MOŻE pojawiać się w innych sieciach i witrynach internetowych oraz być widoczny w wyszukiwarkach internetowych. Jeśli nie chcesz tego domyślnego zachowania, dostosuj ustawienia swojego kanału i ogranicz listę osób, które mogą oglądać Twoje treści.
|
||||
|
||||
**Komentarze i wpisy na forach**
|
||||
|
||||
Komentarze do postów stworzonych przez innych oraz posty oznaczone jako posty na forum należą do Ciebie jako twórcy (autora), ale ich dystrybucja nie jest pod Twoją bezpośrednią kontrolą i zrzekasz się NIEKTÓRYCH praw do tych elementów. Te posty i komentarze MOGĄ być ponownie rozpowszechniane wśród innych i MOGĄ być widoczne dla każdego w internecie. W przypadku komentarzy, twórca "pierwszej wiadomości" w wątku (rozmowie), na który odpowiadasz, kontroluje dystrybucję wszystkich komentarzy i odpowiedzi na tę wiadomość. Jest on "właścicielem" i dlatego ma określone prawa w odniesieniu do całej rozmowy (w tym wszystkich zawartych w niej komentarzy). Nadal możesz edytować lub usuwać komentarz, ale właściciel konwersacji ma również prawa do edytowania, usuwania, ponownej dystrybucji i tworzenia kopii zapasowych i przywracania dowolnej lub całej zawartości konwersacji.
|
||||
Komentarze do wpisów stworzonych przez innych oraz wpisy oznaczone jako wpisy na forum należą do Ciebie jako twórcy (autora), ale ich dystrybucja nie jest pod Twoją bezpośrednią kontrolą i zrzekasz się NIEKTÓRYCH praw do tych elementów. Te wpisy i komentarze MOGĄ być ponownie rozpowszechniane wśród innych i MOGĄ być widoczne dla każdego w internecie. W przypadku komentarzy, twórca "pierwszej wiadomości" w wątku (rozmowy), na który odpowiadasz, kontroluje dystrybucję wszystkich komentarzy i odpowiedzi na tę wiadomość. Jest on "właścicielem" i dlatego ma określone prawa w odniesieniu do całej rozmowy (w tym wszystkich zawartych w niej komentarzy). Nadal możesz edytować lub usuwać komentarz, ale właściciel rozmowy ma również prawa do edytowania, usuwania, ponownej dystrybucji i tworzenia kopii zapasowych i przywracania dowolnej lub całej zawartości rozmowy.
|
||||
|
||||
**Informacja prywatna**
|
||||
|
||||
Programiści $Projectname zapewnią, że każda dostarczona przez Ciebie zawartość oznaczona jako PRYWATNA będzie chroniona przed podsłuchem - najlepiej jak potrafią. Zawartość kanału prywatnego MOŻE być widoczna w bazie danych każdego zaangażowanego administratora centrum, ale prywatne wiadomości są ukrywane w bazie danych. To ostatnie oznacza, że jest to bardzo trudne, ale NIE niemożliwe, aby te treści były widoczne dla administratora centrum. Treść kanału prywatnego i wiadomości prywatne są również usuwane z powiadomień e-mail. Pełne szyfrowanie jest oferowane jako funkcja opcjonalna i NIE MOŻE być widoczne, nawet dla zdeterminowanego administratora.
|
||||
Programiści $Projectname zapewnią, że każda dostarczona przez Ciebie zawartość oznaczona jako PRYWATNA będzie chroniona przed podsłuchem - najlepiej jak potrafią. Zawartość kanału prywatnego MOŻE być widoczna w bazie danych każdego zaangażowanego administratora węzła, ale prywatne wiadomości są ukrywane w bazie danych. To ostatnie oznacza, że jest to bardzo trudne, ale NIE niemożliwe, aby te treści były widoczne dla administratora węzła. Treść kanału prywatnego i wiadomości prywatne są również usuwane z powiadomień e-mail. Pełne szyfrowanie jest oferowane jako funkcja opcjonalna i NIE MOŻE być widoczne, nawet dla zdeterminowanego administratora.
|
||||
|
||||
[h5]Prywatność tożsamości[/h5]
|
||||
|
||||
Prywatność dla Twojej tożsamości to kolejny aspekt. Ponieważ masz zdecentralizowaną tożsamość w $Projectname, Twoja prywatność wykracza poza domowy hub. Jeśli chcesz mieć pełną kontrolę nad swoją prywatnością i bezpieczeństwem, powinieneś uruchomić własny hub na dedykowanym serwerze. Dla wielu osób jest to skomplikowane ale może poszerzyć ich możliwości techniczne. Wymieńmy więc kilka środków ostrożności, które możesz podjąć, aby zapewnić sobie jak największą prywatność.
|
||||
Prywatność dla Twojej tożsamości to kolejny aspekt. Ponieważ masz zdecentralizowaną tożsamość w $Projectname, Twoja prywatność wykracza poza domowy węzeł. Jeśli chcesz mieć pełną kontrolę nad swoją prywatnością i bezpieczeństwem, powinieneś uruchomić własny węzeł na dedykowanym serwerze. Dla wielu osób jest to skomplikowane ale może poszerzyć ich możliwości techniczne. Wymieńmy więc kilka środków ostrożności, które możesz podjąć, aby zapewnić sobie jak największą prywatność.
|
||||
|
||||
Zdecentralizowana tożsamość ma wiele zalet i daje wiele interesujących funkcji, ale powinieneś być świadomy faktu, że Twoja tożsamość jest znana innym hubom w sieci $Projectname. Jedną z tych zalet jest to, że inne kanały mogą udostępniać dostosowane treści i umożliwiać oglądanie prywatnych rzeczy (takich jak prywatne zdjęcia, które inni chcą Ci udostępnić). Z tego powodu te kanały muszą wiedzieć, kim jesteś. Ale rozumiemy, że czasami te inne kanały wiedzą od Ciebie więcej, niż byś sobie tego życzył. Na przykład wtyczka Visage, która może poinformować właściciela kanału o ostatniej wizycie w jego profilu. Możesz łatwo zrezygnować z tego niskiego poziomu i uważamy, że jest to nieszkodliwe śledzenie.
|
||||
Zdecentralizowana tożsamość ma wiele zalet i daje wiele interesujących funkcji, ale powinieneś być świadomy faktu, że Twoja tożsamość jest znana innym węzłom w sieci $Projectname. Jedną z tych zalet jest to, że inne kanały mogą udostępniać dostosowane treści i umożliwiać oglądanie prywatnych rzeczy (takich jak prywatne zdjęcia, które inni chcą Ci udostępnić). Z tego powodu te kanały muszą wiedzieć, kim jesteś. Ale rozumiemy, że czasami te inne kanały wiedzą od Ciebie więcej, niż byś sobie tego życzył. Na przykład wtyczka Visage, która może poinformować właściciela kanału o ostatniej wizycie w jego profilu. Możesz łatwo zrezygnować z tego niskiego poziomu i uważamy, że jest to nieszkodliwe śledzenie.
|
||||
|
||||
* Możesz włączyć [Do Not Track (DNT)](http://donottrack.us/) w swojej przeglądarce internetowej. Szanujemy tą nową propozycję polityki prywatności. Wszystkie nowoczesne przeglądarki obsługują DNT. Znajdziesz to w ustawieniach prywatności swojej przeglądarki lub możesz zapoznać się z instrukcją przeglądarki internetowej. Nie wpłynie to na funkcjonalność $Projectname. To ustawienie jest prawdopodobnie wystarczające dla większości ludzi.
|
||||
* Możesz włączyć [url=http://donottrack.us/]Do Not Track (DNT)[/url] w swojej przeglądarce internetowej. Szanujemy tą nową propozycję polityki prywatności. Wszystkie nowoczesne przeglądarki obsługują DNT. Znajdziesz to w ustawieniach prywatności swojej przeglądarki lub możesz zapoznać się z instrukcją przeglądarki internetowej. Nie wpłynie to na funkcjonalność $Projectname. To ustawienie jest prawdopodobnie wystarczające dla większości ludzi.
|
||||
|
||||
* Możesz [wyłączyć publikację](ustawienia) swojego kanału w naszym katalogu kanałów. Jeśli chcesz, aby ludzie mogli znaleźć Twój kanał, podaj im adres swojego kanału. Uważamy, że jest to dobra wskazówka, że wolisz dodatkową prywatność i automatycznie włączasz opcję "Nie śledź", jeśli tak jest.
|
||||
* Możesz [url=[baseurl]/settings]wyłączyć publikację[/url] swojego kanału w naszym katalogu kanałów. Jeśli chcesz, aby ludzie mogli znaleźć Twój kanał, podaj im adres swojego kanału. Uważamy, że jest to dobra wskazówka, że wolisz dodatkową prywatność i automatycznie włączasz opcję "Nie śledź", jeśli tak jest.
|
||||
|
||||
* Możesz mieć zablokowany hub. Oznacza to, że wszystkie kanały i treści w tym centrum nie są publiczne ani widoczne dla świata zewnętrznego. To jest coś, co może zrobić tylko administrator centrum. Szanujemy to również i automatycznie włączamy opcję "Nie śledź:, jeśli jest ustawiona.
|
||||
* Możesz mieć zablokowany węzeł. Oznacza to, że wszystkie kanały i treści w tym wężle nie są publiczne ani widoczne dla świata zewnętrznego. To jest coś, co może zrobić tylko administrator węzła. Szanujemy to również i automatycznie włączamy opcję "Nie śledź:, jeśli jest ustawiona.
|
||||
|
||||
[h5]Cenzura[/h5]
|
||||
|
||||
$Projectname to globalna sieć obejmująca wszystkie religie i kultury. Nie oznacza to, że każdy członek sieci czuje się tak samo jak Ty w spornych kwestiach, a niektórzy ludzie mogą MOCNO sprzeciwić się publikowanym przez Ciebie treściom. Ogólnie rzecz biorąc, jeśli chcesz opublikować coś, o czym wiesz, że nie jest powszechnie akceptowane, najlepszym rozwiązaniem jest ograniczenie odbiorców za pomocą kontroli prywatności do małego kręgu znajomych.
|
||||
|
||||
$Projectname jako dostawca sieci nie może cenzurować zawartości. Jednak administratorzy hubów MOGĄ cenzurować wszelkie treści, które pojawiają się w ich hubie, aby zachować zgodność z lokalnym prawem, a nawet osobistym osądem. Ich decyzja jest ostateczna. Jeśli masz problemy z jakimkolwiek administratorem huba, możesz przenieść swoje konto i wpisy do innej witryny, która jest bardziej zgodna z Twoimi oczekiwaniami. Sprawdzaj (okresowo) [Warunki świadczenia usług](help/TermsOfService) swojego huba, aby poznać wszelkie zasady lub wytyczne. Jeśli Twoje treści składają się z materiałów, które są nielegalne lub mogą powodować problemy, MOCNO zachęcamy do hostowania własnych (zostań administratorem własnego huba). Mimo to. możesz stwierdzić, że Twoje treści są zablokowane w niektórych hubach, ale $Projectname jako sieć nie może wogóle zablokować ich publikowania.
|
||||
$Projectname jako dostawca sieci nie może cenzurować zawartości. Jednak administratorzy węzłów MOGĄ cenzurować wszelkie treści, które pojawiają się w ich węźle, aby zachować zgodność z lokalnym prawem, a nawet osobistym osądem. Ich decyzja jest ostateczna. Jeśli masz problemy z jakimkolwiek administratorem węzła, możesz przenieść swoje konto i wpisy do innej witryny, która jest bardziej zgodna z Twoimi oczekiwaniami. Sprawdzaj (okresowo) [Warunki świadczenia usług](help/TermsOfService) swojego węzła, aby poznać wszelkie zasady lub wytyczne. Jeśli Twoje treści składają się z materiałów, które są nielegalne lub mogą powodować problemy, MOCNO zachęcamy do hostowania własnych (zostań administratorem własnego węzła). Mimo to. możesz stwierdzić, że Twoje treści są zablokowane w niektórych węzłach, ale $Projectname jako sieć nie może wogóle zablokować ich publikowania.
|
||||
|
||||
$Projectname ZALECA, aby administratorzy hubów zapewnili okres karencji wynoszący 1-2 dni między ostrzeżeniem właściciela konta o treści, którą należy usunąć, a fizycznym usunięciem lub wyłączeniem konta. Dzięki temu właściciel treści będzie mógł wyeksportować metadane swojego kanału i zaimportować je do innej witryny. W rzadkich przypadkach treść może mieć taki charakter, że uzasadnia natychmiastowe zamknięcie konta. To jest decyzja właściciela huba, a nie decyzja $Projectname.
|
||||
$Projectname ZALECA, aby administratorzy węzłów zapewnili okres karencji wynoszący 1-2 dni między ostrzeżeniem właściciela konta o treści, którą należy usunąć, a fizycznym usunięciem lub wyłączeniem konta. Dzięki temu właściciel treści będzie mógł wyeksportować metadane swojego kanału i zaimportować je do innej witryny. W rzadkich przypadkach treść może mieć taki charakter, że uzasadnia natychmiastowe zamknięcie konta. To jest decyzja właściciela węzła, a nie decyzja $Projectname.
|
||||
|
||||
Jeśli zazwyczaj i regularnie publikujesz treści dla dorosłych lub obraźliwe, MOCNO zachęcamy do oznaczenia swojego konta jako „NSFW” (Not Safe For Work). Zapobiegnie to wyświetlaniu Twojego zdjęcia profilowego w katalogu, z wyjątkiem przeglądających, którzy zdecydowali się wyłączyć „tryb bezpieczny”. Jeśli administratorzy katalogu uznają Twoje zdjęcie profilowe za nieobyczajne lub obraźliwe, administrator katalogu MOŻE oznaczyć Twoje zdjęcie profilowe jako NSFW. Obecnie nie ma oficjalnego mechanizmu do zakwestionowania lub cofnięcia tej decyzji, dlatego NALEŻY oznaczyć własne konto jako NSFW, jeśli może być nieodpowiednie dla ogółu odbiorców.
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ W przeciwieństwie do innych usług, $Projectname oferuje Ci możliwość tworze
|
||||
[i]Potraktuj swój profil jako podstawowe informacje o sobie, które przekazujesz innym osobom.[/i]
|
||||
|
||||
[b]Kanał[/b]
|
||||
Podczas rejestracji tworzysz swój pierwszy [i]kanał[/i]. Podobnie jak w przypadku profili, możesz mieć kilka kanałów. Na początku może to być nieco zagmatwane, ale wyjaśnijmy to. Masz już jeden kanał. Możesz używać go dla publicznie, aby komunikować się z ludźmi w codziennym życiu. Ale być może jesteś zapalonym czytelnikiem książek i wielu ludzi się tym nudzi. Otwierasz więc [i]drugi kanał[/i] tylko dla miłośników książek, na którym wszyscy mogą rozmawiać o książkach tyle, ile chcesz. Oczywiście jest to nowy strumień postów, z nowym profilem (... lub nowymi profilami ...) i zupełnie innymi kontaktami. Niektóre połączenia mogą istnieć w obu kanałach, ale będą takie, które dotyczą tylko jednego z nich. Ty sam po prostu przełączasz się między nimi, tak jak w prawdziwym życiu, kiedy rozmawiasz z ludźmi, których spotykasz na ulicy lub z osobami, które spotykasz specjalnie, aby porozmawiać o książkach. Możesz nawet połączyć się ze sobą lub lepiej: z innym kanałem. :)
|
||||
Podczas rejestracji tworzysz swój pierwszy [i]kanał[/i]. Podobnie jak w przypadku profili, możesz mieć kilka kanałów. Na początku może to być nieco zagmatwane, ale wyjaśnijmy to. Masz już jeden kanał. Możesz używać go dla publicznie, aby komunikować się z ludźmi w codziennym życiu. Ale być może jesteś zapalonym czytelnikiem książek i wielu ludzi się tym nudzi. Otwierasz więc [i]drugi kanał[/i] tylko dla miłośników książek, na którym wszyscy mogą rozmawiać o książkach tyle, ile chcesz. Oczywiście jest to nowy strumień wpisów, z nowym profilem (... lub nowymi profilami ...) i zupełnie innymi kontaktami. Niektóre połączenia mogą istnieć w obu kanałach, ale będą takie, które dotyczą tylko jednego z nich. Ty sam po prostu przełączasz się między nimi, tak jak w prawdziwym życiu, kiedy rozmawiasz z ludźmi, których spotykasz na ulicy lub z osobami, które spotykasz specjalnie, aby porozmawiać o książkach. Możesz nawet połączyć się ze sobą lub lepiej: z innym kanałem. :)
|
||||
[i]Pomyśl o kanale jako o różnych przestrzeniach poświęconych różnym tematom, w których spotykasz się z różnymi ludźmi.[/i]
|
||||
|
||||
#include doc/macros/pl/main_footer.bb;
|
||||
|
||||
@@ -14,7 +14,7 @@ któremu chcesz zrobić niespodziankę. W tym przypadku ustawiasz "Pokaż" grupi
|
||||
</p>
|
||||
|
||||
<dl class="text-info dl-terms-large dl-horizontal">
|
||||
<dt style="width: 3em;">Wskazówka!</td>
|
||||
<dt style="width: 3em;">Wskazówka!</dt>
|
||||
<dd style="margin-left: 4em;">
|
||||
Kolor obramowania każdego kanału wskazuje, czy ten kanał — lub jedną z grup,
|
||||
do której należy — będzie mieć dostęp do wpisu. Kolor obramowania będzie
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[h3]Wtyczki/Dodatki[/h3]
|
||||
[list=1]
|
||||
[*] abcjsplugin - tworzenie zapisów nitowych w swoich wpisach
|
||||
[*] abcjsplugin - tworzenie zapisów nutowych w swoich wpisach
|
||||
[*] adultphotoflag - zapobiega wyświetlaniu zdjęć NSFW w albumach publicznych
|
||||
[*] authchoose - wysyłanie potwierdzenia tożsamości tylko do witryn znajomych
|
||||
[*] b2tbtn - zapewnia przycisk powodujący przejście bezpośrednio na górę strony, jeśli przewinie się dużo treści dół okna
|
||||
@@ -10,7 +10,7 @@
|
||||
[*] calc - kalkulator naukowy
|
||||
[*] chess - interaktywne gry w szachy z uwzględnieniem tożsamości międzydomenowej
|
||||
[*] chords - generowanie wykresów palcowania i alternatyw dla każdego znanego akordu gitarowego
|
||||
[*] custom_home - ustawianie własnej strony jako strony początkowej huba
|
||||
[*] custom_home - ustawianie własnej strony jako strony początkowej węzła
|
||||
[*] diaspora - emulator protokołu Diaspora
|
||||
[*] dirstats - wyświetlanie interesujących statystyk generowanych przez serwer katalogowy
|
||||
[*] docs - alternatywne strony dokumentacji
|
||||
@@ -18,7 +18,7 @@
|
||||
[*] dreamhost - zapewnia bardziej niezawodną usługę na hostingu współdzielonym Dreamhost
|
||||
[*] dwpost - krzyżowe wpisy do Dreamwidth
|
||||
[*] emojione - zezwala na uzywanie emojis jako emotikonów
|
||||
[*] extcron - stosowanie zewnętrznej usługi cron do uruchamiania zaplanowanych zadań huba
|
||||
[*] extcron - stosowanie zewnętrznej usługi cron do uruchamiania zaplanowanych zadań węzła
|
||||
[*] firefox - dostarcza link do zainstalowania API Sharing Firefoxa
|
||||
[*] flattrwidget - dostarcza przyciski "Flattr Us"
|
||||
[*] flip - tworzenie odwróconego tekstu
|
||||
@@ -28,7 +28,7 @@
|
||||
[*] gnusoc - protokół GNU-Social (OStatus). W tworzeniu.
|
||||
[*] hexit - narzędzie do konwersji szesnastkowej
|
||||
[*] hilite - umożliwia podświetlanie bloków kodu, specyficzne dla języka programowania, zawartych we wpisach
|
||||
[*] hubwall - wysyłanie wiadomosci e-mail administratora na wszystkie konta w hubie
|
||||
[*] hubwall - wysyłanie wiadomosci e-mail administratora na wszystkie konta w węźle
|
||||
[*] ijpost - krzyżówe wpisy do Insanejournal
|
||||
[*] irc - połączenie z czatami IRC
|
||||
[*] jappixmini - czat XMPP
|
||||
@@ -51,7 +51,7 @@
|
||||
[*] noembed - używanie noembed.com jako dodatku do natywnej funkcjonalności oembed w $Projectname (obecnie nie działa)
|
||||
[*] nofed - zapobiega "federacji" wpisów w kanale, utrzymuje całą interakcję na stronie właściciela kanału
|
||||
[*] nsabait - dodawaj do swoich wpisów losowe hashtagi związane z terroryzmem
|
||||
[*] nsfw - bardzo polecana wtyczka do zwijania postów z nieodpowiednimi treściami
|
||||
[*] nsfw - bardzo polecana wtyczka do zwijania wpisów z nieodpowiednimi treściami
|
||||
[*] openclipatar - wybór zdjęcia profilowego spośród setek obrazów bez tantiem
|
||||
[*] openid - uwierzytelnianie OpenID i serwer OpenID. Twój adres URL OpenID to [observer.baseurl]/id/[observer.webname]
|
||||
[*] opensearch - umożliwienie swojej witrynie stania się dostawcą wyszukiwania w przeglądarce
|
||||
@@ -81,7 +81,7 @@
|
||||
[*] statusnet - wpisy krzyżówe do GNU-social i StatusNet [zrl=[baseurl]/help/addons_gnusocial]Posting To Gnu Social[/zrl]
|
||||
[*] std_embeds - umożłiwia niefiltrowane osadzanie dla popularnych dostawców strumieni, takich jak youtube, vimeo i soundcloud
|
||||
[*] superblock - bardzo zalecane - całkowite blokowanie obraźliwuch kanałów w swoim strumieniu
|
||||
[*] testdrive - zmienia hub w witrynę testową z kontami, które wygasają po okresie próbnym
|
||||
[*] testdrive - zmienia węzęł w witrynę testową z kontami, które wygasają po okresie próbnym
|
||||
[*] tictac - 3D tic-tac-toe
|
||||
[*] torch - aplikacja podświetlania (flashlight)
|
||||
[*] tour - prezentacja funkcji dla nowych członków
|
||||
|
||||
@@ -12,7 +12,7 @@ Ikona. Pobierz ikonę $Projectname znajdującą się pod tym linkiem, po zapisan
|
||||
|
||||
https://framagit.org/hubzilla/core/blob/master/images/rm-32.png
|
||||
|
||||
Nazwa. Nadaj aplikacji odpowiednią nazwę. Wywołaj swoją witrynę hubzilli. Możesz preferować r2g.
|
||||
Nazwa. Nadaj aplikacji odpowiednią nazwę. Wywołaj swoją witrynę Hubzilli. Możesz preferować r2g.
|
||||
|
||||
Opis. Użyj tego pola, aby opisać przeznaczenie aplikacji. Dodaj coś o efekcie użycia krzyżowego wysyłania z $Projectname do GNUsocial.
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
### 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 blog. 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ć.
|
||||
|
||||
### Gdzie można znaleźć więcej pomocy
|
||||
|
||||
Jeśli napotkasz problemy lub sam masz jakiś problem, które nie zostały opisane w tej dokumentacji, poinformuj nas o tym za pośrednictwem narzędzia do [śledzenia problemów na Github](https://framagit.org/hubzilla/core/issues). Prosimy o jak najdokładniejsze opisanie swojego środowiska operacyjnego i podanie jak największej ilości informacji o wszelkich komunikatach o błędach, które mogą się pojawić, abyśmy mogli zapobiec ich występowaniu w przyszłości. Ze względu na dużą różnorodność istniejących systemów operacyjnych i platform PHP możemy mieć ograniczone możliwości debugowania instalacji PHP lub pozyskiwania brakujących modułów, ale dołożymy wszelkich starań, aby rozwiązać wszelkie ogólne problemy z kodem.
|
||||
Jeśli napotkasz problemy lub sam masz jakiś problem, które nie zostały opisane w tej dokumentacji, poinformuj nas o tym za pośrednictwem narzędzia do [śledzenia problemów na serwisie Framagit](https://framagit.org/hubzilla/core/issues). Prosimy o jak najdokładniejsze opisanie swojego środowiska operacyjnego i podanie jak największej ilości informacji o wszelkich komunikatach o błędach, które mogą się pojawić, abyśmy mogli zapobiec ich występowaniu w przyszłości. Ze względu na dużą różnorodność istniejących systemów operacyjnych i platform PHP możemy mieć ograniczone możliwości debugowania instalacji PHP lub pozyskiwania brakujących modułów, ale dołożymy wszelkich starań, aby rozwiązać wszelkie ogólne problemy z kodem.
|
||||
|
||||
### Zanim zaczniesz
|
||||
|
||||
@@ -20,25 +20,25 @@ POWINNO się używać SSL. Jeśli używasz SSL, MUSISZ użyć certyfikatu uznawa
|
||||
|
||||
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.
|
||||
To ograniczenie zostało wprowadzone, ponieważ Twoje publiczne wpisy mogą zawierać odniesienia do obrazów na Twoim węźle. Inni członkowie przeglądający swój strumień na innych węzłach otrzymają w swojej przeglądarce ostrzeżenia, jeśli Twój certyfikat nie jest zaufany. To może zmylić wiele osób, ponieważ jest to zdecentralizowana sieć i otrzymają ostrzeżenie o Twoim węźle podczas przeglądania własnego węzła i mogą pomyśleć, że ich własny węzeł 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ć i podporządkuje się zaleceniom przeglądarki. Jest to destrukcyjne dla społeczności. 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 - szyfrowanie połączeń HTTP jest konieczne.
|
||||
|
||||
Bezpłatne certyfikaty zgodne z przeglądarkami są dostępne od dostawców, takich jak StartSSL i LetsEncrypt.
|
||||
Bezpłatne certyfikaty zgodne z przeglądarkami są dostępne od dostawców, takich jak StartSSL czy 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 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.
|
||||
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 serwerami internetowymi.
|
||||
|
||||
### Wdrożenie
|
||||
|
||||
Nowy hub można wdrożyć na kilka sposobów:
|
||||
Nowy węzeł można wdrożyć na kilka sposobów:
|
||||
|
||||
* ręczna inastalaja na istniejącym serwerze;
|
||||
* automatyczna instalacja na istniejącym serwerze przy użyciu skryptu instalacyjnego;
|
||||
* automatyczne wdrożenie przy użyciu prywatnego serwera wirtualnego OpenShift (VPS).)
|
||||
* 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_
|
||||
@@ -204,7 +204,7 @@ jest nieco bardziej restrykcyjny w zakresie dozwolonych rodzajów komunikacji. W
|
||||
|
||||
* _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
|
||||
Każdy członek Twojej sieci 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
|
||||
@@ -214,7 +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_. Dla przykładu utwórzmy klasę standard i premium, używając następujący kod:
|
||||
|
||||
// Service classes
|
||||
|
||||
@@ -263,21 +263,22 @@ Aby zastosować klasę usług do istniejącego konta, użyj narzędzia wiersza p
|
||||
|
||||
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 `blogchan` na klasę _firstclass_ (z potwierdzeniem)
|
||||
|
||||
util/service_class --channel=bdziennikchan firstclass
|
||||
util/service_class --channel=blogchan firstclass
|
||||
|
||||
**Opcje limitu klas usług**
|
||||
|
||||
##### Opcje limitów klas usług:
|
||||
|
||||
* _photo_upload_limit_ - maksymalna łączna liczba bajtów na zdjęcia
|
||||
* _photo_upload_limit_ - maksymalna łączna powierzchnia dysku na przesłane pliki (w bajtach)
|
||||
* _attach_upload_limit_ - maksymalna powierzchnia dysku na przesyłane załączniki plikow (w bajtach)
|
||||
* _total_items_ - maksymalna liczba wpisów na najwyższym poziomie
|
||||
* _total_pages_ - maksymalna liczba stron comanche
|
||||
* _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
|
||||
@@ -312,7 +313,7 @@ Na stronie katalogu kanałów może pojawiać się chmura słów kluczowych. Je
|
||||
|
||||
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 węzeł 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 ""
|
||||
|
||||
@@ -326,7 +327,7 @@ Istnieje kilka sposobów, w jakie może to się nie powieść i pozostawić syst
|
||||
|
||||
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.
|
||||
Węzeł 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
|
||||
|
||||
@@ -340,17 +341,16 @@ W przypadku błędów "500: problemy mogą być często rejestrowane w dziennika
|
||||
|
||||
Istnieją trzy różne obiekty dziennika.
|
||||
|
||||
**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).
|
||||
**Pierwsza to dziennik błędów bazy danych**. Jest on używane tylko wtedy, gdy utworzy się plik o 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";
|
||||
**Drugi to dziennik błędów PHP**. Plik **_php.out_** 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.
|
||||
**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. Jego nazwę (ścieżkę) trzeba podać na stronie "Administracja - Logi" (/admin/logs), np. *hubzilla.log* wskazuje na plik o tej nazwie zlokalizowany w katalogu głównym Hubzilla. Czasem zgłaszane są 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. Te błędy mogą być "śmiertelne", ale też niegroźne i 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 nam 100 milionów zrzutów, bo tylko nas wkurzysz! Tylko kilka odpowiednich wierszy, ab można było 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.
|
||||
To są dzienniki Twojego serwisu. 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.
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
### Hub Snapshot Tools
|
||||
### Narzędzia migawek węzła
|
||||
|
||||
Programiści Hubzilli często muszą przełączać się między gałęziami, które mogą
|
||||
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
|
||||
folderze i zawiera on określone katalogi i szczegóły bazy danych huba.
|
||||
folderze i zawiera on określone katalogi i szczegóły bazy danych węzłaa.
|
||||
|
||||
### Konfiguracja
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
[h2]Dokumentacja dla administratorów huba[/h2]
|
||||
[h3]Wdrozenie swojego huba[/h3]
|
||||
[h2]Dokumentacja dla administratorów węzła[/h2]
|
||||
[h3]Wdrozenie swojego węzła[/h3]
|
||||
[zrl=[baseurl]/help/install]Instalacja[/zrl]
|
||||
[zrl=[baseurl]/help/red2pi]Instalowanie $Projectname na Raspberry Pi[/zrl]
|
||||
[zrl=[baseurl]/help/Hubzilla_on_OpenShift]$Projectname na OpenShift[/zrl]
|
||||
[h3]Utrzymywanie swojego huba[/h3]
|
||||
[h3]Utrzymywanie swojego węzła[/h3]
|
||||
[zrl=[baseurl]/help/troubleshooting]Wskazówki dotyczące rozwiązywania problemów[/zrl]
|
||||
[zrl=[baseurl]/help/theme_management]Zarządzanie motywami[/zrl]
|
||||
[zrl=[baseurl]/help/hidden_configs]Poprawianie ukrytych konfiguracji $Projectname[/zrl]
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
|
||||
$Projectname Community Server to oprogramowanie typu Open Source, które jest utrzymywane przez "społeczność" - zasadniczo nieopłacanych ochotników. Nikt nie jest odpowiedzialny za naprawianie błędów. Pracujemy razem, aby oprogramowanie i sieć działały płynnie i bez błędów. Jesteś członkiem tej społeczności, więc potrzebujemy również Twojej pomocy, aby zapewnić wysokiej jakości oprogramowanie. Nie ma mitycznych "programistów", którzy w magiczny sposób wszystko naprawiają. Do nas wszystkich należy włączenie się i pomoc.
|
||||
|
||||
Pierwszą rzeczą, którą musisz zrobić, jest porozimieć się z administratorem huba - osobą, która obsługuje Twoją witrynę i zarządza nią. Znajdują się ona w wyjątkowej sytuacji, ponieważ ma dostęp do wewnętrznego oprogramowania i bazy danych oraz [b]plików dziennika[/b] i będzie musiała zaangażować się w naprawę problemu. Inne osoby "w sieci" nie mogą naprawdę Ci tym pomóc. Pierwszą rzeczą, jaką musi zrobić administrator huba, jest przejrzenie dzienników i podjecie próby odtworzenia problemu. Dlatego staraj się być tak pomocny i uprzejmy, jak to tylko możliwe, pomagając mu przyjrzeć się problemowi.
|
||||
Pierwszą rzeczą, którą musisz zrobić, jest porozimieć się z administratorem węzła - osobą, która obsługuje Twoją witrynę i zarządza nią. Znajdują się ona w wyjątkowej sytuacji, ponieważ ma dostęp do wewnętrznego oprogramowania i bazy danych oraz [b]plików dziennika[/b] i będzie musiała zaangażować się w naprawę problemu. Inne osoby "w sieci" nie mogą naprawdę Ci tym pomóc. Pierwszą rzeczą, jaką musi zrobić administrator węzła, jest przejrzenie dzienników i podjecie próby odtworzenia problemu. Dlatego staraj się być tak pomocny i uprzejmy, jak to tylko możliwe, pomagając mu przyjrzeć się problemowi.
|
||||
|
||||
Aby znaleźć swojego administratora huba (jeśli nie wiesz, kim on jest), zajrzyj na [url=[baseurl]/siteinfo]tą stronę[/url]. Jeśli nie podał on żadnych informacji kontaktowych na tej stronie lub nie podał "Impressum", zobacz [url=[baseurl]/siteinfo.json]podsumowanie informacji o tej witrynie[/url] znajdujące się pod nagłówkiem "admin:".
|
||||
Aby znaleźć swojego administratora węzła (jeśli nie wiesz, kim on jest), zajrzyj na [url=[baseurl]/siteinfo]tą stronę[/url]. Jeśli nie podał on żadnych informacji kontaktowych na tej stronie lub nie podał "Impressum", zobacz [url=[baseurl]/siteinfo.json]podsumowanie informacji o tej witrynie[/url] znajdujące się pod nagłówkiem "admin:".
|
||||
|
||||
Zdecydowanie zaleca się, aby administratorzy huba wypełniali raporty o błędach, tak aby możliwe było dołączenie odpowiedniego plik dziennika i informacji z bazy danych istotnych dla problemu oraz aby byli oni gotowi do wypróbowania rozwiązań i testów uzupełniających. Bez tego poziomu współpracy rozwiązanie problemu może nie być możliwe.
|
||||
Zdecydowanie zaleca się, aby administratorzy węzła wypełniali raporty o błędach, tak aby możliwe było dołączenie odpowiedniego plik dziennika i informacji z bazy danych istotnych dla problemu oraz aby byli oni gotowi do wypróbowania rozwiązań i testów uzupełniających. Bez tego poziomu współpracy rozwiązanie problemu może nie być możliwe.
|
||||
|
||||
[h3]Jestem administratorem huba, co mam zrobić?[/h3]
|
||||
[h3]Jestem administratorem węzła, co mam zrobić?[/h3]
|
||||
|
||||
Oprogramowania zapewniające tą usługę sieciową jest typu Open Source i jest dostępne do wglądu. Zachęcamy wszystkich do zapoznania się z kodem i zobaczenia, jak wszystko działa i sprawdzenia, czy nie robimy nic złego lub niedbałego. Jeśli został zgłoszony komunikat o błędzie, często można przeszukać pliki źródłowe tego komunikatu o błędzie i dowiedzieć się, co go spowodowało. Dzięki tym informacjom i plikom dziennika serwisu możliwe będzie ustalenie sekwencji zdarzeń prowadzących do błędu. Problem mogą powodować również serwisy zewnętrzne i jego źródłem wcale nie musi być Twój serwis, ale inne miejsce w sieci. Spróbuj określić punkty końcowe komunikacji (huby lub serwisy), których dotyczy problem i skontaktuj się z administratorem tego serwisu lub tych serwisów. Spróbuj podać czas zdarzenia, w którym coś poszło nie tak, aby można go było znaleźć w dziennikach. Współpracuj z innymi administratorami, aby spróbować znaleźć przyczynę problemu. Pliki dziennika są Twoim przyjacielem. Kiedy w oprogramowaniu dzieje się coś, czego się nie spodziewaliśmy, prawie zawsze zostało to zarejestrowane.
|
||||
Oprogramowania zapewniające tą usługę sieciową jest typu Open Source i jest dostępne do wglądu. Zachęcamy wszystkich do zapoznania się z kodem i zobaczenia, jak wszystko działa i sprawdzenia, czy nie robimy nic złego lub niedbałego. Jeśli został zgłoszony komunikat o błędzie, często można przeszukać pliki źródłowe tego komunikatu o błędzie i dowiedzieć się, co go spowodowało. Dzięki tym informacjom i plikom dziennika serwisu możliwe będzie ustalenie sekwencji zdarzeń prowadzących do błędu. Problem mogą powodować również serwisy zewnętrzne i jego źródłem wcale nie musi być Twój serwis, ale inne miejsce w sieci. Spróbuj określić punkty końcowe komunikacji (węzły lub serwisy), których dotyczy problem i skontaktuj się z administratorem tego serwisu lub tych serwisów. Spróbuj podać czas zdarzenia, w którym coś poszło nie tak, aby można go było znaleźć w dziennikach. Współpracuj z innymi administratorami, aby spróbować znaleźć przyczynę problemu. Pliki dziennika są Twoim przyjacielem. Kiedy w oprogramowaniu dzieje się coś, czego się nie spodziewaliśmy, prawie zawsze zostało to zarejestrowane.
|
||||
|
||||
[h3]Biały ekran śmierci[/h3]
|
||||
|
||||
@@ -27,5 +27,5 @@ Jeśli członkowie społeczności z wykształceniem i doświadczeniem w zakresie
|
||||
|
||||
Następnie musisz zaczekać. Jeśli jest to poważny problem, może zostać szybko rozwiązany, ale nikt nie jest odpowiedzialny za naprawianie błędów. Jeśli problem utrzymuje się bez rozwiązania, poświęć trochę czasu na zbadanie samemu problemu. Zapytaj o wszystko, czego nie rozumiesz a co jest związane z tym problemem. Dowiesz się więcej o tym, jak działa oprogramowanie i prawdopodobnie dowiesz się, dlaczego teraz nie działa. Ostatecznie to ktoś w społeczności ma zamiar to naprawić, a ty jesteś członkiem społeczności. Tak właśnie działa proces Open Source.
|
||||
|
||||
Inne osoby pracujące nad rozwiązaniem problemu mogą potrzebować dowiedzieć się więcej, więc odrób swoją pracę domową i udokumentuj, co się dzieje i wszystko, czego próbowałeś. Nie mów "Zrobiłem xyz i to nie działa". To nam nic nie mówi. Powiedz nam dokładnie, jakie kroki podjąłeś i jaki był rezultat, a także co się w rezultacie wydarzyło. Jaką stronę (URL) przeglądałeś lub jaki formularz wypełniałeś? Jeśli były jakieś komunikaty o błędach, nie mów "wystąpił komunikat o błędzie". Powiedz nam dokładnie, o czym była wiadomość. Powiedz nam również, z jakiego huba korzystasz, jakiej wersji oprogramowania używasz i wszelkie inne szczegóły, które mogą być unikalne na temat konfiguracji Twojej witryny. Rozumie się, że możesz chcieć zachować prywatność niektórych informacji i swoich połączeń, jednak jeśli nie chcesz udostępniać informacji potrzebnych innym osobom do odtworzenia i rozwiązania problemu, może on nie zostać naprawiony.
|
||||
Inne osoby pracujące nad rozwiązaniem problemu mogą potrzebować dowiedzieć się więcej, więc odrób swoją pracę domową i udokumentuj, co się dzieje i wszystko, czego próbowałeś. Nie mów "Zrobiłem xyz i to nie działa". To nam nic nie mówi. Powiedz nam dokładnie, jakie kroki podjąłeś i jaki był rezultat, a także co się w rezultacie wydarzyło. Jaką stronę (URL) przeglądałeś lub jaki formularz wypełniałeś? Jeśli były jakieś komunikaty o błędach, nie mów "wystąpił komunikat o błędzie". Powiedz nam dokładnie, o czym była wiadomość. Powiedz nam również, z jakiego węzła korzystasz, jakiej wersji oprogramowania używasz i wszelkie inne szczegóły, które mogą być unikalne na temat konfiguracji Twojej witryny. Rozumie się, że możesz chcieć zachować prywatność niektórych informacji i swoich połączeń, jednak jeśli nie chcesz udostępniać informacji potrzebnych innym osobom do odtworzenia i rozwiązania problemu, może on nie zostać naprawiony.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[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.
|
||||
Na Twoim węźle 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 wpisó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:
|
||||
|
||||
|
||||
93
doc/pl/directories.bb
Normal file
93
doc/pl/directories.bb
Normal file
@@ -0,0 +1,93 @@
|
||||
[h3]Konfiguracja katalogu[/h3]
|
||||
|
||||
Katalogi w $Projectname służą do wyszukiwania i lokalizowania członków w całej sieci Zot. Są również używane do przechowywania i wysyłania zapytań o "oceny" członków i serwisów. Katalogi są dystrybuowane i dublowane, więc awaria jednej z nich nie spowoduje wyłączenia lub zakłócenia całej sieci.
|
||||
|
||||
[b]Standardowa konfiguracja[/b]
|
||||
|
||||
Nowe serwisy działają zaraz po uruchomieniu jako klienty katalogi będą, podczas pierwszego uruchomienia, automatycznie wybierać serwery katalogowe z zakodowanej listy. Możesz przeanalizować lub zmienić tą cechę za pomocą polecenia:
|
||||
|
||||
[code]
|
||||
util/config system directory_server
|
||||
[/code]
|
||||
|
||||
Aby ustawić inny serwer katalogowy:
|
||||
|
||||
[code]
|
||||
util/config system directory_server https://newdirectory.something
|
||||
[/code]
|
||||
|
||||
[b]Konfiguracja autonomicznego sewera[/b]
|
||||
|
||||
Niektóre serwisy mogą chcieć działać w trybie "autonomicznym" i nie łączyć się z żądnymi zewnętrznymi serwerami katalogami. Jest to przydatne w przypadku serwisów izolowanych ("poza siecią") i serwisów testowych, ale może być również przydatne dla małych organizacji, które nie chcą łączyć się z innymi serwisami w sieci.
|
||||
|
||||
Aby to skonfigurować, poszukaj w swoim pliku .htconfig.php następującego tekstu i odpowiednio ustaw konfigurację.
|
||||
|
||||
[code]
|
||||
// Configure how we communicate with directory servers.
|
||||
// DIRECTORY_MODE_NORMAL = directory client, we will find a directory
|
||||
// DIRECTORY_MODE_SECONDARY = caching directory or mirror
|
||||
// DIRECTORY_MODE_PRIMARY = main directory server
|
||||
// DIRECTORY_MODE_STANDALONE = "off the grid" or private directory services
|
||||
|
||||
App::$config['system']['directory_mode'] = DIRECTORY_MODE_STANDALONE;
|
||||
[/code]
|
||||
|
||||
|
||||
[b]Konfiguracja serwera pomocniczego[/b]
|
||||
|
||||
Można także skonfigurować swoją witrynę jako serwer pomocniczy. Działa to jako kopia lustrzana katalogu głównego i umożliwia podział obciążenia między dostępne serwery. Istnieje bardzo niewielka różnica funkcjonalna między podstawowym i pomocniczym serwerem, jednak może istnieć tylko jeden główny serwer katalogowy na dziedzinę (dziedziny są omówione w dalszej części tego dokumentu).
|
||||
|
||||
Przed zdecydowaniem się na obsługę serwera katalogowego należy pamiętać, że trzeba być aktywnym członkiem sieci oraz mieć zasoby i czas do zarządzania tymi usługami. Zwykle nie wymaga to specjalnego zarządzania, ale niezbędna jest większa stabilność, ponieważ utrata serwera katalogów może powodować problemy z klientami katalogów, którzy są od niego zależni.
|
||||
|
||||
|
||||
[b]Konfiguracja serwera katalogowego[/b]
|
||||
|
||||
Jeśli serwer katalogowy wskazuje, że nie jest już serwerem katalogów, powinno to zostać wykryte przez oprogramowanie i konfiguracja tego serwera zostanie usunięta (wygaszona). Jeśli przejdzie w tryb offline na stałe bez ostrzeżenia, będziesz wiedzieć tylko wtedy, gdy członkowie witryny zgłoszą, że katalogi są niedostępne. Obecnie administrator witryny może to naprawić tylko ręcznie, wybierając nowy katalog i wykonując polecenie:
|
||||
|
||||
[code]
|
||||
util/config system directory_server https://newdirectory.something
|
||||
[/code]
|
||||
|
||||
Mamy nadzieję, że w przyszłości będzie to konfigurowane w polu do wyboru w panelu administracyjnego serwisu.
|
||||
|
||||
|
||||
[h2]Dziedziny katalogów[/h2]
|
||||
|
||||
Duże organizacje mogą chcieć używać "dziedzin" katalogów zamiast pojedynczego samodzielnego katalogu. Dziedzina standardowa i domyślna jest znana jako RED_GLOBAL. Tworząc nową dziedzinę, organizacja ma możliwość tworzenia własnej hierarchii serwerów głównych i pomocniczych oraz klientów.
|
||||
|
||||
[code]
|
||||
util/config system directory_realm MY_REALM
|
||||
[/code]
|
||||
|
||||
Twoja dziedzina musi mieć katalog główny. Utwórz to najpierw. Następnie ustaw tę samą dziedzinę we wszystkich serwisach w dziedzinie katalogu (serwerach i klientach).
|
||||
|
||||
Możesz także podać "dziedzinę podrzędną", która działa niezależnie od dziedziny RED_GLOBAL (lub dowolnej innej dziedziny), ale umożliwia wzajemne członkostwo i pewne możliwości wyszukiwania członków w całej przestrzeni katalogu. To przeszło tylko lekkie testy, więc przygotuj się na pomoc i naprawienie wszelkich problemów, które mogą się pojawić. Dziedzina podrzędna zawiera dziedzinę nadrzędną w nazwie dziedziny.
|
||||
|
||||
|
||||
[code]
|
||||
util/config system directory_realm RED_GLOBAL:MY_REALM
|
||||
[/code]
|
||||
|
||||
|
||||
[b]Dostęp do dziedziny[/b]
|
||||
|
||||
Można zrobić tak, aby Twoje serwery katalogowe i usługi były używane tylko przez członków Twojej dziedziny. W tym celu trzeba zastosować podawanie tokenu lub hasła, aby uzyskać dostęp do usług katalogowych dziedziny. Ten token nie jest szyfrowany podczas przesyłania, ale jest wystarczający, aby zapobiec przypadkowemu dostępowi do serwerów katalogowych. Dla wszystkich lokacji (klientów i serwerów katalogowych) w dziedzinie należy skonfigurować następujące elementy:
|
||||
|
||||
[code]
|
||||
util/config system realm_token my-secret-realm-password
|
||||
[/code]
|
||||
|
||||
|
||||
[h2]Katalogi lustrzane[/h2]
|
||||
|
||||
Dublowanie odbywa się przy uzyciu dziennika transakcji, które są współużytkowane przez serwery katalogowe. W przypadku aktualizacji katalogu i profilu przesyłany jest adres kanału przeprowadzającego aktualizację, a inne serwery katalogów sondują ten kanał u źródła pod kątem zmian. Nie ufamy i nie powinniśmy ufać żadnym informacjom przekazanym nam przez inne serwery katalogowe. Informacje zawsze trzeba sprawdzać u źródła.
|
||||
|
||||
Oceny są obsługiwane nieco inaczej - zaszyfrowany pakiet (podpisany przez kanał, który utworzył ocenę) jest przesyłany między serwerami. Ten podpis musi zostać zweryfikowany przed zaakceptowaniem oceny. Oceny są zawsze publikowane na głównym serwerze katalogów i stamtąd propagowane do wszystkich innych serwerów katalogów. Z tego powodu w dziedzinie może istnieć tylko jeden serwer główny. Jeśli źle skonfigurowana witryna twierdzi, że jest katalogiem głównym, jest ignorowana w dziedzinie RED_GLOBAL. W innych dzidzinach obecnie nie ma takiej ochrony. Należy o tym pamiętać podczas pracy z alternatywnymi dziedzinami.
|
||||
|
||||
Nowo utworzone serwery katalogowe nie otrzymują "pełnego zrzutu", ale ze względu na wydajność i minimalne zakłócenia działania innych serwerów w sieci, są one powoli przełączane do trybu online. Może minąć nawet miesiąc, zanim nowy pomocniczy serwer katalogowy zapewni pełny widok sieci. Nie dodawaj żadnych serwerów pomocniczych do zakodowanej listy rezerwowych serwerów katalogowych, dopóki nie będą one działać jako katalog przez co najmniej miesiąc.
|
||||
|
||||
Wszystkie kanały są skonfigurowane do "pingowania" swojego serwera katalogowego raz w miesiącu, w nieco losowych momentach w ciągu miesiąca. Daje to katalogowi możliwość wykrywania martwych kanałów i witryn (przestają one pingować). Następnie są oznaczane jako martwe lub nieosiągalne i z czasem będą usuwane z wyników katalogu.
|
||||
|
||||
Kanały można skonfigurować tak, aby były "ukryte" w katalogu. Te kanały mogą nadal istnieć w katalogu, ale nie będzie można ich przeszukiwać, a niektóre "wrażliwe" informacje osobiste nie będą w ogóle przechowywane.
|
||||
|
||||
|
||||
41
doc/pl/feature/additional/access.md
Normal file
41
doc/pl/feature/additional/access.md
Normal file
@@ -0,0 +1,41 @@
|
||||
## Kontrola dostępu i uprawnienia
|
||||
|
||||
|
||||
### Prywatne grupy
|
||||
|
||||
Włączenie zarządzania i wybóru grup prywatności.
|
||||
<!-- TODO: full description for Privacy Groups -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 0
|
||||
|
||||
|
||||
### Wiele profili
|
||||
|
||||
Możliwość tworzenia wielu profili.
|
||||
<!-- TODO: full description for Multiple Profiles -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 3
|
||||
|
||||
|
||||
### Kategorie uprawnień
|
||||
|
||||
Podawanie alternatywnego ograniczenia uprawnień dla połączeń.
|
||||
<!-- TODO: full description for Permission Categories -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 2
|
||||
|
||||
|
||||
### Klienty OAuth
|
||||
|
||||
Zarządzaj tokenami uwierzytelniającymi dla aplikacji mobilnych i zdalnych.
|
||||
<!-- TODO: full description for OAuth Clients -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 1
|
||||
|
||||
|
||||
### Tokeny dostępu
|
||||
|
||||
Utwórz tokeny dostępu, aby osoby niebędące członkami mogły uzyskać dostęp do treści prywatnych.
|
||||
<!-- TODO: full description for Access Tokens -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 2
|
||||
0
doc/pl/feature/additional/calendar.md
Normal file
0
doc/pl/feature/additional/calendar.md
Normal file
64
doc/pl/feature/additional/composition.md
Normal file
64
doc/pl/feature/additional/composition.md
Normal file
@@ -0,0 +1,64 @@
|
||||
## Funkcje tworzenia wpisów
|
||||
|
||||
### Duże obrazy
|
||||
|
||||
Możliwość dołączania do wpisów dużych (1024px) miniatur zdjęć. Jeśli ta opcja nie jest jest włączona, będą uzywane małe miniatury (640 pikseli)
|
||||
<!-- TODO: full description for Large Photos -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 1
|
||||
|
||||
|
||||
### Źródła kanałów
|
||||
|
||||
Automatyczne importowanie zawartośvi kanału z innych kanałów lub źródeł
|
||||
<!-- TODO: full description for Channel Sources -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 3
|
||||
|
||||
|
||||
### Jeszcze więcej szyfrowania
|
||||
|
||||
Zezwalaj na opcjonalne szyfrowanie zawartości *end-to-end* za pomocą wspólnego tajnego klucza
|
||||
<!-- TODO: full description for Even More Encryption -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 3
|
||||
|
||||
|
||||
### Włącz narzędzia do głosowania
|
||||
|
||||
Podaj klasę wpisów, na które inni mogą głosować
|
||||
<!-- TODO: full description for Enable Voting Tools -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 3
|
||||
|
||||
|
||||
### Wyłączenie komentowania
|
||||
|
||||
Zapewnia opcję wyłączenia komentarzy do wpisu
|
||||
<!-- TODO: full description for Disable Comments -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 2
|
||||
|
||||
|
||||
### Opóźnione wysyłanie
|
||||
|
||||
Zezwolenie na publikację wpisów w późniejszym terminie
|
||||
<!-- TODO: full description for Delayed Posting -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 2
|
||||
|
||||
|
||||
### Wygasanie treści
|
||||
|
||||
Usuwanie wpisów i komentarzy albo prywatnych wiadomości w przyszłości.
|
||||
<!-- TODO: full description for Content Expiration -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 1
|
||||
|
||||
|
||||
### Pomijanie powielonych wpisów i komentarzy
|
||||
|
||||
Zapobiega publikowaniu wpisów o identycznej treści zapisanych mniej niż dwie minuty między zgłoszeniami.
|
||||
<!-- TODO: full description for Suppress Duplicate Posts/Comments -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 1
|
||||
59
doc/pl/feature/additional/filtering.md
Normal file
59
doc/pl/feature/additional/filtering.md
Normal file
@@ -0,0 +1,59 @@
|
||||
[ftset]: /settings/features "Dodatkowe funkcjonalności"
|
||||
|
||||
## Sieć i filtrowanie strumienia
|
||||
|
||||
|
||||
### Wyszukiwanie wg daty
|
||||
|
||||
> Dostępna na stronie ...
|
||||
|
||||
Możliwość wyboru wpisów według zakresów dat.
|
||||
<!-- TODO: full description for Search by Date -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 1
|
||||
|
||||
### Zapisywane wyszukiwanie
|
||||
|
||||
> dostępna na stronie [Dodatkowe funkcjonalności] [ftset]
|
||||
|
||||
Zapis wyszukiwanego hasła do ponownego wykorzystania
|
||||
<!-- TODO: full description for Saved Searches -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 2
|
||||
|
||||
### Karta "Osobista sieć"
|
||||
|
||||
Włącza zakładkę, aby wyświetlać tylko wpisy sieciowe, z którymi uzytkownik miał interakcję.
|
||||
<!-- TODO: full description for Network Personal Tab -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 1
|
||||
|
||||
### Karta "Nowa sieć"
|
||||
|
||||
Włącza kartę, aby wyświetlić całą nową aktywność sieciową.
|
||||
<!-- TODO: full description for Network New Tab -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 2
|
||||
|
||||
|
||||
### Narzędzie zaprzyjaźnienia
|
||||
|
||||
Filtruje aktywność strumienia według głębokości relacji.
|
||||
<!-- TODO: full description for Affinity Tool -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 1
|
||||
|
||||
### Sugerowane kanały
|
||||
|
||||
Pokazuje sugestie dotyczące znajomych i połączeń.
|
||||
<!-- TODO: full description for Suggest Channels -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 1
|
||||
|
||||
|
||||
### Filtrowanie połączenia
|
||||
|
||||
Filtrowanie przychodzących wpisów na podstawie słów kluczowych lub treści (fraz).
|
||||
<!-- TODO: full description for Connection Filtering -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 3
|
||||
128
doc/pl/feature/additional/general.md
Normal file
128
doc/pl/feature/additional/general.md
Normal file
@@ -0,0 +1,128 @@
|
||||
## Funkcje ogólne
|
||||
|
||||
### Linki dla nowych członków
|
||||
|
||||
Wyświetla skrótowe menu z linkami dla nowych członków.
|
||||
<!-- TODO: full description for New Member Links -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 1
|
||||
|
||||
|
||||
### Zaawansowane profile
|
||||
|
||||
Dodatkowe sekcje profilu i pól wyboru.
|
||||
<!-- TODO: full description for Advanced Profiles -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 1
|
||||
|
||||
|
||||
### Import/Export profili
|
||||
|
||||
Zapisywanie i ładowanie szczegółów profilu ze stronu *sites/channels*
|
||||
<!-- TODO: full description for Profile Import/Export -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 3
|
||||
|
||||
|
||||
### Strony internetowe
|
||||
|
||||
Udostępnienie zarządzania stronami internetowymi na swoim kanale
|
||||
<!-- TODO: full description for Web Pages -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 3
|
||||
|
||||
|
||||
### Wiki
|
||||
|
||||
Dostarcza wiki dla kanału
|
||||
<!-- TODO: full description for Wiki -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 2
|
||||
|
||||
|
||||
### Prywatne notatki
|
||||
|
||||
Udostępnia narzędzie do przechowywania notatek i przypomnień (uwaga: niezaszyfrowane)
|
||||
<!-- TODO: full description for Private Notes -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 1
|
||||
|
||||
|
||||
### Karty
|
||||
|
||||
Tworzenie osobistych kart zadań
|
||||
<!-- TODO: full description for Cards -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 1
|
||||
|
||||
|
||||
### Artykuły
|
||||
|
||||
Tworzenie interaktywnych artykułów
|
||||
<!-- TODO: full description for Articles -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 1
|
||||
|
||||
|
||||
### Wybór kanału nawigacji
|
||||
|
||||
Umożliwienia zmiany kanału bezpośrednio z rozwijanego menu nawigacji
|
||||
<!-- TODO: full description for Navigation Channel Select -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 3
|
||||
|
||||
|
||||
### Lokalizacja zdjecia
|
||||
|
||||
Połączenie z mapą danych lokalizacyjnych zdjęcia, jeśli są dostępne w przesłanym zdjęciu.
|
||||
<!-- TODO: full description for Photo Location -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 2
|
||||
|
||||
|
||||
### Dostęp do kontrolowanych czatów
|
||||
|
||||
Zapewnij pokoje rozmów i usługi czatu z kontrolą dostępu.
|
||||
<!-- TODO: full description for Access Controlled Chatrooms -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 1
|
||||
|
||||
|
||||
### Inteligentne urodziny
|
||||
|
||||
Informowanie o strefie czasowej wydarzeń urodzinowych, jeśli znajomi są rozproszeni po całej globie.
|
||||
<!-- TODO: full description for Smart Birthdays -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 2
|
||||
|
||||
|
||||
### Wybór strefy czasowej zdarzeń
|
||||
|
||||
Umożliwia tworzenie wydarzeń w strefach czasowych innych niż autora kanału.
|
||||
<!-- TODO: full description for Event Timezone Selection -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 2
|
||||
|
||||
|
||||
### Kanał premium
|
||||
|
||||
Pozwala ustawić ograniczenia i warunki łączenia się ze swoim kanałem
|
||||
<!-- TODO: full description for Premium Channel -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 4
|
||||
|
||||
|
||||
### Zaawansowane przeszukiwanie katalogu
|
||||
|
||||
Umożliwia tworzenie złożonych zapytań wyszukiwania w katalogu.
|
||||
<!-- TODO: full description for Advanced Directory Search -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 4
|
||||
|
||||
|
||||
### Zaawansowane ustawienia motywu i układu
|
||||
|
||||
Umożliwia precyzyjne dostosowywanie motywów i układów stron
|
||||
<!-- TODO: full description for Advanced Theme and Layout Settings -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 4
|
||||
123
doc/pl/feature/additional/overview.md
Normal file
123
doc/pl/feature/additional/overview.md
Normal file
@@ -0,0 +1,123 @@
|
||||
[ftset]: /settings/features "Dodatkowe funkcjonalności"
|
||||
|
||||
## Dodatkowe możliwości
|
||||
|
||||
W $Projectname, oprócz podstawowych ustawień konta i kanałów, każdy użytkownik może również zarządzać dodatkowymi funkcjonalościami związanymi ze swoim kontem i kanałami. Może to robić na stronie [Dodatkowe funkcjonalności] [ftset].
|
||||
|
||||
Oto omówienie dostępnych tam opcji, tak jak są wyświetlane na stronie [Dodatkowe funkcjonalności] [ftset]:
|
||||
|
||||
<h3 id="calendar_settings">Kalendarz</h3>
|
||||
Są to opcje, które można dodatkow włączyć dla wszystkich swoich kalendarzy. Można to zmienić indywidualnie w każdym kalendarzu.
|
||||
|
||||
<h4>Rozpocznij tydzień kalendarzowy w poniedziałek</h4>
|
||||
W kalendarzach $Projectname, domyślnie jest to niedziela.
|
||||
|
||||
<h4>Wybór strefy czasowej wydarzenia</h4>
|
||||
Zezwolenie na tworzenie wydarzeń w strefach czasowych innych niż strefa ustawiona dla kanału.
|
||||
|
||||
<h3 id="channel_main_page_settings">Strona główna kanału</h3>
|
||||
Kilka dodatkowych możliwości związanych ze stroną główną kanału.
|
||||
|
||||
<h4>Wyszukaj po dacie</h4>
|
||||
Możliwość wyboru wpisów według zakresów dat
|
||||
|
||||
<h4>Chmura tagów</h4>
|
||||
Udostępnienie osobistej chmury tagów na stronie swojego kanału
|
||||
<!-- TODO: full description for Tag Cloud -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 2
|
||||
|
||||
<h4>Użyj trybu bloga/listy</h4>
|
||||
Komentarze będą wyświetlane osobno
|
||||
|
||||
<h3 id="connections_settings">Połączenia</h3>
|
||||
Obecnie jest tu tylko ustawienie opcji umożliwiającej filtrowanie strumienia wg słów kluczowych lub treści (fraz).
|
||||
|
||||
<h3 id="conversation_settings">Rozmowa</h3>
|
||||
Kilka dodatkowych opcji rozszerzających obsługę rozmów (i dyskusji).
|
||||
|
||||
<h3 id="directory_settings">Katalog</h3>
|
||||
Dostępna tu opcja zaawansowanego przeszukiawania katalogu może być bardzo użyteczna dla osób chcących dotrzeć do konkretnych informacji publikowanych w sieci Hubzilla.
|
||||
|
||||
<h4>Zaawansowane przeszukiwanie katalogu</h4>
|
||||
Umożliwia tworzenie złożonych zapytań wyszukiwania w katalogu.
|
||||
|
||||
<!-- TODO: full description for Advanced Directory Search -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 4
|
||||
|
||||
<h3 id="manage_settings">Zarządzanie</h3>
|
||||
Dostępna tu opcja włącza funkcję zmiany kanału bezpośrednio z rozwijanego menu nawigacji.
|
||||
|
||||
<h3 id="network_settings">Sieć</h3>
|
||||
Znajduje się tu szereg opcji włączających funkcje związane z siecią i strumieniem sieciowym. Przede wszystkim dostępnych jest tu kilka dodatkowych filtrów i inne użyteczne funkcje.
|
||||
|
||||
<h4>Filtr wydarzeń</h4>
|
||||
Możliwość wyświetlania tylko wydarzeń
|
||||
|
||||
<h4>Filtr ankiet</h4>
|
||||
Możliwość wyświetlania tylko ankiet
|
||||
|
||||
<h4>Zapisywane wyszukiwanie</h4>
|
||||
Zapisywanie wyszukiwanych haseł do ponownego wykorzystania
|
||||
|
||||
<!-- TODO: full description for Saved Searches -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 2
|
||||
|
||||
<h4>Zapisywane foldery</h4>
|
||||
Możliwość umieszczania wpisów w folderach
|
||||
<!-- TODO: full description for Saved Folders -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych do korzystania z tej funkcji: 2
|
||||
|
||||
<h4>Alternatywna kolejność strumienia</h4>
|
||||
Możliwość uporządkowania strumienia według daty ostatniego wpisu, daty ostatniego komentarza lub nieprzeczytanych aktywności
|
||||
|
||||
<h4>Filtr kontaktów</h4>
|
||||
Możliwość wyświetlania wpisów autorstwa tylko wybranego kontaktu
|
||||
|
||||
<h4>Filtr forów</h4>
|
||||
Możliwość wyświetlania wpisów tylko z określonego forum
|
||||
|
||||
<h4>Filtr wpisów osobistych</h4>
|
||||
Możliwość wyświetlania tylko tych wpisów, z którymi miało się interakcję
|
||||
|
||||
<h4>Użyj trybu bloga/listy</h4>
|
||||
Komentarze będą wyświetlane osobno
|
||||
|
||||
<h3 id="photos_settings">Zdjęcia</h3>
|
||||
|
||||
<h4>Lokalizacja zdjecia</h4>
|
||||
|
||||
Połączenie z mapą danych lokalizacyjnych zdjęcia, jeśli są dostępne w przesłanym zdjęciu
|
||||
|
||||
<!-- TODO: full description for Photo Location -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 2
|
||||
|
||||
<h3 id="profiles_settings">Profile</h3>
|
||||
W tej sekcji zawarte są opcje włączające dodatkowe funkcje dotyczące profilu. Jeśli chcesz i możesz zakładać na swoim koncie wiele profili (i tożsamości), włącz tu opcję "wiele profili".
|
||||
|
||||
<h4>Profile zaawansowane</h4>
|
||||
|
||||
Dodatkowe sekcje profilu i pól wyborów
|
||||
<!-- TODO: full description for Advanced Profiles -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 1
|
||||
|
||||
<h4>Import/Export profilu</h4>
|
||||
Zapisywanie i ładowanie szczegółów profilu ze stronu <i>sites/channels</i>.
|
||||
<!-- TODO: full description for Profile Import/Export -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 3
|
||||
|
||||
<h4>Wiele profili</h4>
|
||||
Umożliwienie tworzenia wielu profili i tożsamości, jeśli parametry konta to dozwalają.
|
||||
|
||||
Powszechną praktyka jest limitowanie przydzielonych użytkownikowi zasobów serwera w ramach konta. Ogranicza się nie tylko powierzchnie dyskową ale i też ilość profili i tozsamości, jakie uzytkownik moze utworzyć.
|
||||
<!-- TODO: full description for Multiple Profiles -->
|
||||
|
||||
Wymagany minimalny poziom umiejętności technicznych, aby używać tę funkcję: 3
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user