mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-23 17:55:46 -04:00
Compare commits
424 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6de327402b | ||
|
|
131ce826c3 | ||
|
|
a3f4ad9ea0 | ||
|
|
ec3b1131d9 | ||
|
|
74c0345009 | ||
|
|
628b03da29 | ||
|
|
bd59fb0b4e | ||
|
|
443b436be8 | ||
|
|
343f3059e6 | ||
|
|
ba22d3e9b6 | ||
|
|
657af3024e | ||
|
|
7d82a34538 | ||
|
|
a0b788e96a | ||
|
|
b63aa3079b | ||
|
|
2171686284 | ||
|
|
b382edc61d | ||
|
|
5ae21d04b0 | ||
|
|
2980f852aa | ||
|
|
5e07ebe7fa | ||
|
|
e9088bd52e | ||
|
|
92ea7fcfb1 | ||
|
|
64181c7cf1 | ||
|
|
8a0c7b3fe1 | ||
|
|
587e790892 | ||
|
|
f73a83aa55 | ||
|
|
513cf2b8e2 | ||
|
|
7d4e07df79 | ||
|
|
8211bc09d4 | ||
|
|
5705005ca3 | ||
|
|
79b4642b32 | ||
|
|
c9981ff0e1 | ||
|
|
0948b061fe | ||
|
|
a537e78f14 | ||
|
|
25edeebf2b | ||
|
|
a7a4727591 | ||
|
|
bc2afb21e1 | ||
|
|
64fe93b9eb | ||
|
|
33d2a852c9 | ||
|
|
300679c053 | ||
|
|
f9c85c52f3 | ||
|
|
98985b2761 | ||
|
|
8fe00d428d | ||
|
|
02229482b8 | ||
|
|
9a5c1aa02f | ||
|
|
a46e340a13 | ||
|
|
70c3cd99ac | ||
|
|
e89bbde575 | ||
|
|
2ee1e2af72 | ||
|
|
c3ad21c548 | ||
|
|
635a24dff4 | ||
|
|
a03423794a | ||
|
|
d4e723a8eb | ||
|
|
ded9f18b8a | ||
|
|
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 | ||
|
|
0ebb1f685f | ||
|
|
805a25eb62 | ||
|
|
4ca12afc9d | ||
|
|
6cfa2572a8 | ||
|
|
04ec986bf7 | ||
|
|
ee453c4acc | ||
|
|
4d3524ba9d | ||
|
|
29beea28c2 | ||
|
|
e2a289d614 | ||
|
|
59d3483a06 | ||
|
|
a99161abdf | ||
|
|
79d48dc92b | ||
|
|
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 | ||
|
|
82192d1ead | ||
|
|
7ee495624e | ||
|
|
64bbbc8053 | ||
|
|
4d3d868d19 | ||
|
|
45cc2d7bd8 | ||
|
|
15b45af550 | ||
|
|
91ebfbc215 | ||
|
|
011342ac1b | ||
|
|
5577383a48 | ||
|
|
dc336010db | ||
|
|
88fbeaddb0 | ||
|
|
7612d8246e | ||
|
|
53bb16e799 | ||
|
|
ed04104250 | ||
|
|
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 | ||
|
|
97e483d684 | ||
|
|
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 |
97
CHANGELOG
97
CHANGELOG
@@ -1,3 +1,100 @@
|
||||
Hubzilla 5.6.1 (2021-06-04)
|
||||
- Update spanish translations
|
||||
- Fix login name label if register email verification is disabled
|
||||
- Fix zotinfo issue with deleted channels
|
||||
- Make pubstream ordering configurable
|
||||
- Fix article summary duplicated when editing
|
||||
- Update polish translations
|
||||
- Fix admin setting for invitations not displayed correctly
|
||||
- Fix registration in invite only mode
|
||||
- Fix notifications not returning offset -1 when returning early
|
||||
- Fix direct messages for items imported via sync
|
||||
- Bring back the channel protocols hooks
|
||||
- Fix security headers switching
|
||||
- Fix magic auth for delegated channels
|
||||
- Introduce drop_query_params() for secure query parameter removal
|
||||
- PHP8 fixes (ongoing)
|
||||
- Fix menu wrapping regression
|
||||
|
||||
Addons
|
||||
- LDAPauth: fix regression creating an account
|
||||
- Twitter: allow feeds crossposting
|
||||
- Twitter: fix posting when post by default is disabled
|
||||
- Pubcrawl: add litepub directMessage attribute
|
||||
- Pubcrawl: allow xchan/hubloc upgrades from e.g. ostatus
|
||||
- Diaspora: fix possible issue with missing hublocs
|
||||
- Diaspora: refine dispatching of public of public items
|
||||
|
||||
|
||||
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
|
||||
- Fix rendering of long text in xchan vcard
|
||||
- Fix local link for rss content if rewrite author is sets
|
||||
- Fix regression in mod display
|
||||
|
||||
Addons
|
||||
- Pubcrawl: fix issue with following/unfollowing a thread
|
||||
- Pubcrawl: more robust implementation of mastodon remote reply
|
||||
- Photocache: remove suffix from the cached photo URL
|
||||
|
||||
|
||||
Hubzilla 5.4.1 (2021-03-09)
|
||||
- Fix profile not found if not logged in
|
||||
- Fix summary not reset on cancel
|
||||
- Fix summary not saved with aoutosave draft
|
||||
- Fix unexpected trigger of buttons when pressing enter in input fields
|
||||
- Fix spanish plural expression
|
||||
- Fix undefined page-end on non dynamic pages
|
||||
|
||||
Addons
|
||||
- Pubcrawl: fix regression in pubcrawl_follow_mod_init()
|
||||
|
||||
|
||||
Hubzilla 5.4 (2021-03-08)
|
||||
- Add new connections to privacy group independend from the default privacy group settings
|
||||
- group_add() return group hash to save a lookup
|
||||
|
||||
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,14 @@ class Cron {
|
||||
db_utcnow()
|
||||
);
|
||||
|
||||
require_once('include/account.php');
|
||||
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 +134,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 +195,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 +241,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();
|
||||
|
||||
|
||||
@@ -331,6 +331,12 @@ class Notifier {
|
||||
return;
|
||||
}
|
||||
|
||||
// follow/unfollow is for internal use only
|
||||
if (in_array($target_item['verb'], [ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
|
||||
logger('not fowarding follow/unfollow note activity');
|
||||
return;
|
||||
}
|
||||
|
||||
if (strpos($target_item['postopts'], 'nodeliver') !== false) {
|
||||
logger('notifier: target item is undeliverable', LOGGER_DEBUG);
|
||||
return;
|
||||
|
||||
@@ -29,6 +29,7 @@ class Onedirsync {
|
||||
|
||||
if (!$r)
|
||||
return;
|
||||
|
||||
if (($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (!$r[0]['ud_addr']))
|
||||
return;
|
||||
|
||||
@@ -59,13 +60,12 @@ class Onedirsync {
|
||||
|
||||
$h = Libzot::zot_record_preferred($h);
|
||||
|
||||
if (($h) && ($h['hubloc_status'] & HUBLOC_OFFLINE)) {
|
||||
if (($h) && (($h['hubloc_status'] & HUBLOC_OFFLINE) || $h['hubloc_deleted'] || $h['hubloc_error']) ) {
|
||||
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,50 +160,6 @@ class Onepoll {
|
||||
}
|
||||
}
|
||||
|
||||
/* if ($fetch_feed) {
|
||||
|
||||
if (strpos($contact['xchan_connurl'], z_root()) === 0) {
|
||||
// local channel - save a network fetch
|
||||
$c = channelx_by_hash($contact['xchan_hash']);
|
||||
if ($c) {
|
||||
$x = [
|
||||
'success' => true,
|
||||
'body' => json_encode([
|
||||
'success' => true,
|
||||
'messages' => zot_feed($c['channel_id'], $importer['xchan_hash'], ['mindate' => $last_update])
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// remote fetch
|
||||
|
||||
$feedurl = str_replace('/poco/', '/zotfeed/', $contact['xchan_connurl']);
|
||||
$feedurl .= '?f=&mindate=' . urlencode($last_update) . '&zid=' . $importer['channel_address'] . '@' . App::get_hostname();
|
||||
$recurse = 0;
|
||||
$x = z_fetch_url($feedurl, false, $recurse, ['session' => true]);
|
||||
}
|
||||
|
||||
logger('feed_update: ' . print_r($x, true), LOGGER_DATA);
|
||||
}
|
||||
|
||||
if (($x) && ($x['success'])) {
|
||||
$total = 0;
|
||||
logger('onepoll: feed update ' . $contact['xchan_name'] . ' ' . $feedurl);
|
||||
|
||||
$j = json_decode($x['body'], true);
|
||||
if ($j['success'] && $j['messages']) {
|
||||
foreach ($j['messages'] as $message) {
|
||||
$results = process_delivery(['hash' => $contact['xchan_hash']], get_item_elements($message),
|
||||
[['hash' => $importer['xchan_hash']]], false);
|
||||
logger('onepoll: feed_update: process_delivery: ' . print_r($results, true), LOGGER_DATA);
|
||||
$total++;
|
||||
}
|
||||
logger("onepoll: $total messages processed");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// update the poco details for this connection
|
||||
$r = q("SELECT xlink_id from xlink where xlink_xchan = '%s' and xlink_updated > %s - INTERVAL %s and xlink_static = 0 limit 1",
|
||||
intval($contact['xchan_hash']),
|
||||
|
||||
@@ -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",
|
||||
@@ -376,6 +379,8 @@ class Activity {
|
||||
|
||||
$ret = [];
|
||||
|
||||
|
||||
|
||||
if ($i['verb'] === ACTIVITY_FRIEND) {
|
||||
// Hubzilla 'make-friend' activity, no direct mapping from AS1 to AS2 - make it a note
|
||||
$objtype = 'Note';
|
||||
@@ -570,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];
|
||||
@@ -579,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -607,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:
|
||||
@@ -638,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) {
|
||||
@@ -651,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']);
|
||||
@@ -695,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;
|
||||
@@ -719,7 +726,6 @@ class Activity {
|
||||
$ret = [];
|
||||
$reply = false;
|
||||
|
||||
|
||||
if ($i['verb'] === ACTIVITY_FRIEND) {
|
||||
// Hubzilla 'make-friend' activity, no direct mapping from AS1 to AS2 - make it a note
|
||||
$ret['obj'] = [];
|
||||
@@ -977,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']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1090,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'],
|
||||
@@ -1122,7 +1115,7 @@ class Activity {
|
||||
|
||||
static function encode_item_object($item, $elm = 'obj') {
|
||||
$ret = [];
|
||||
|
||||
|
||||
if ($item[$elm]) {
|
||||
if (! is_array($item[$elm])) {
|
||||
$item[$elm] = json_decode($item[$elm],true);
|
||||
@@ -1164,6 +1157,7 @@ class Activity {
|
||||
'http://activitystrea.ms/schema/1.0/tag' => 'Add',
|
||||
'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
|
||||
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
|
||||
'http://activitystrea.ms/schema/1.0/stop-following' => 'Unfollow',
|
||||
'http://purl.org/zot/activity/attendyes' => 'Accept',
|
||||
'http://purl.org/zot/activity/attendno' => 'Reject',
|
||||
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
|
||||
@@ -1211,6 +1205,7 @@ class Activity {
|
||||
'http://activitystrea.ms/schema/1.0/tag' => 'Add',
|
||||
'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
|
||||
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
|
||||
'http://activitystrea.ms/schema/1.0/stop-following' => 'Unfollow',
|
||||
'http://purl.org/zot/activity/attendyes' => 'Accept',
|
||||
'http://purl.org/zot/activity/attendno' => 'Reject',
|
||||
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
|
||||
@@ -1328,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
|
||||
@@ -1351,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']) {
|
||||
|
||||
@@ -1362,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':
|
||||
@@ -1427,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);
|
||||
@@ -1448,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']}");
|
||||
@@ -1474,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 = [];
|
||||
@@ -1601,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'];
|
||||
}
|
||||
|
||||
@@ -2093,6 +2088,15 @@ class Activity {
|
||||
|
||||
static function decode_note($act) {
|
||||
|
||||
// Within our family of projects, Follow/Unfollow of a thread is an internal activity which should not be transmitted,
|
||||
// hence if we receive it - ignore or reject it.
|
||||
// Unfollow is not defined by ActivityStreams, which prefers Undo->Follow.
|
||||
// This may have to be revisited if AP projects start using Follow for objects other than actors.
|
||||
|
||||
if (in_array($act->type, [ 'Follow', 'Unfollow' ])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$response_activity = false;
|
||||
|
||||
$s = [];
|
||||
@@ -2111,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']);
|
||||
}
|
||||
|
||||
@@ -2186,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'));
|
||||
@@ -2290,17 +2294,20 @@ class Activity {
|
||||
$s['iconfig'] = $a;
|
||||
}
|
||||
|
||||
if ($act->obj['type'] === 'Note' && $s['attach']) {
|
||||
$s['body'] .= self::bb_attach($s['attach'], $s['body']);
|
||||
}
|
||||
if (array_key_exists('type', $act->obj)) {
|
||||
|
||||
if ($act->obj['type'] === 'Question' && in_array($act->type, ['Create', 'Update'])) {
|
||||
if ($act->obj['endTime']) {
|
||||
$s['comments_closed'] = datetime_convert('UTC', 'UTC', $act->obj['endTime']);
|
||||
if ($act->obj['type'] === 'Note' && $s['attach']) {
|
||||
$s['body'] .= self::bb_attach($s['attach'], $s['body']);
|
||||
}
|
||||
|
||||
if ($act->obj['type'] === 'Question' && in_array($act->type, ['Create', 'Update'])) {
|
||||
if (array_key_exists('endTime', $act->obj)) {
|
||||
$s['comments_closed'] = datetime_convert('UTC', 'UTC', $act->obj['endTime']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($act->obj['closed']) {
|
||||
if (array_key_exists('closed', $act->obj)) {
|
||||
$s['comments_closed'] = datetime_convert('UTC', 'UTC', $act->obj['closed']);
|
||||
}
|
||||
|
||||
@@ -2716,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);
|
||||
}
|
||||
|
||||
@@ -3369,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']);
|
||||
}
|
||||
|
||||
|
||||
@@ -304,11 +304,12 @@ class ActivityStreams {
|
||||
// SECURITY: If we have already stored the actor profile, re-generate it
|
||||
// from cached data - don't refetch it from the network
|
||||
|
||||
$r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
|
||||
$r = q("select * from xchan join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s'",
|
||||
dbesc($x)
|
||||
);
|
||||
if ($r) {
|
||||
$y = Activity::encode_person($r[0]);
|
||||
$r = Libzot::zot_record_preferred($r);
|
||||
$y = Activity::encode_person($r);
|
||||
$y['cached'] = true;
|
||||
return $y;
|
||||
}
|
||||
|
||||
@@ -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']);
|
||||
|
||||
@@ -2925,7 +2924,19 @@ class Libzot {
|
||||
];
|
||||
|
||||
$ret['channel_role'] = get_pconfig($e['channel_id'], 'system', 'permissions_role', 'custom');
|
||||
$ret['protocols'] = ['zot6', 'zot'];
|
||||
|
||||
$hookinfo = [
|
||||
'channel_id' => $id,
|
||||
'protocols' => ['zot6', 'zot']
|
||||
];
|
||||
/**
|
||||
* @hooks channel_protocols
|
||||
* * \e int \b channel_id
|
||||
* * \e array \b protocols
|
||||
*/
|
||||
call_hooks('channel_protocols', $hookinfo);
|
||||
|
||||
$ret['protocols'] = $hookinfo['protocols'];
|
||||
$ret['searchable'] = $searchable;
|
||||
$ret['adult_content'] = $adult_channel;
|
||||
$ret['public_forum'] = $public_forum;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
/*
|
||||
|
||||
@@ -26,7 +26,12 @@ class Activity extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 ";
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
|
||||
|
||||
$i = null;
|
||||
|
||||
@@ -86,7 +91,7 @@ class Activity extends Controller {
|
||||
}
|
||||
|
||||
$parents_str = ids_to_querystr($i,'item_id');
|
||||
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal ",
|
||||
dbesc($parents_str)
|
||||
);
|
||||
@@ -197,8 +202,12 @@ class Activity extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0
|
||||
and item.item_delayed = 0 and item.item_blocked = 0 ";
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
|
||||
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
|
||||
@@ -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"),
|
||||
get_config('system', 'invitation_only', 0)
|
||||
],
|
||||
'$invitation_also' => [
|
||||
'invitation_also',
|
||||
t("Allow invite code"),
|
||||
get_config('system', 'invitation_also', 0)
|
||||
],
|
||||
'$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 ;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@ class Article_edit extends \Zotlabs\Web\Controller {
|
||||
|
||||
$mimetype = $itm[0]['mimetype'];
|
||||
|
||||
$summary = (($itm[0]['summary']) ? '[summary]' . $itm[0]['summary'] . '[/summary]' . "\r\n" : '');
|
||||
$content = $itm[0]['body'];
|
||||
|
||||
$rp = 'articles/' . $channel['channel_address'];
|
||||
@@ -109,7 +108,7 @@ class Article_edit extends \Zotlabs\Web\Controller {
|
||||
'ptyp' => $itm[0]['type'],
|
||||
'mimeselect' => false,
|
||||
'mimetype' => $itm[0]['mimetype'],
|
||||
'body' => $summary . undo_post_tagging($content),
|
||||
'body' => undo_post_tagging($content),
|
||||
'post_id' => $post_id,
|
||||
'visitor' => true,
|
||||
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
|
||||
|
||||
@@ -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,8 +27,8 @@ class Channel extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if (in_array(substr($_GET['search'], 0, 1), ['@', '!', '?']) || strpos($_GET['search'], 'https://') === 0)
|
||||
goaway('search' . '?f=&search=' . $_GET['search']);
|
||||
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;
|
||||
if (argc() > 1)
|
||||
@@ -46,14 +46,22 @@ class Channel extends Controller {
|
||||
}
|
||||
|
||||
$profile = 0;
|
||||
$channel = App::get_channel();
|
||||
|
||||
if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
||||
$channel = App::get_channel();
|
||||
$which = $channel['channel_address'];
|
||||
$profile = argv(1);
|
||||
}
|
||||
|
||||
$channel = channelx_by_nick($which);
|
||||
|
||||
// Do not use channelx_by_nick() here since it will dismiss deleted channels.
|
||||
// We need to provide zotinfo for deleted channels so that directories can pick up the info.
|
||||
$r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_address = '%s' LIMIT 1",
|
||||
dbesc($which)
|
||||
);
|
||||
|
||||
$channel = $r[0];
|
||||
|
||||
if (!$channel) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
@@ -83,12 +91,17 @@ class Channel extends Controller {
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
|
||||
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $data;
|
||||
killme();
|
||||
}
|
||||
|
||||
if ($channel['channel_removed']) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
if (ActivityStreams::is_as_request($channel)) {
|
||||
|
||||
// Somebody may attempt an ActivityStreams fetch on one of our message permalinks
|
||||
@@ -155,7 +168,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 +181,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 +321,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 +341,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 +369,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 +433,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 +499,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) {
|
||||
@@ -243,89 +243,81 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
$item_normal = item_normal();
|
||||
$item_normal_update = item_normal_update();
|
||||
|
||||
$sql_extra = public_permissions_sql($observer_hash);
|
||||
$sql_extra = ((local_channel()) ? EMPTY_STR : item_permissions_sql(0, $observer_hash));
|
||||
|
||||
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) {
|
||||
$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.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
|
||||
(mid = '%s' $sql_extra ))
|
||||
$item_normal
|
||||
limit 1",
|
||||
dbesc($target_item['parent_mid']),
|
||||
intval($sys_id),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
elseif($update && !$load) {
|
||||
require_once('include/channel.php');
|
||||
$sys = get_sys_channel();
|
||||
// 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'
|
||||
$item_normal_update
|
||||
$simple_update
|
||||
LIMIT 1",
|
||||
intval(local_channel()),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
}
|
||||
|
||||
if(! $r) {
|
||||
|
||||
// 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
|
||||
WHERE ( (mid = '%s'
|
||||
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
|
||||
WHERE ((parent_mid = '%s'
|
||||
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
|
||||
(mid = '%s' $sql_extra ) )
|
||||
OR uid = %d ))) OR
|
||||
(parent_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'];
|
||||
if(local_channel()) {
|
||||
$r = q("SELECT item.parent AS item_id from item
|
||||
WHERE uid = %d
|
||||
and parent_mid = '%s'
|
||||
$item_normal_update
|
||||
$simple_update
|
||||
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;
|
||||
$r = q("SELECT item.parent AS item_id from item
|
||||
WHERE parent_mid = '%s'
|
||||
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 )
|
||||
$sql_extra )
|
||||
$item_normal_update
|
||||
$simple_update
|
||||
limit 1",
|
||||
dbesc($target_item['parent_mid']),
|
||||
intval($sysid)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
$r = array();
|
||||
$r = [];
|
||||
}
|
||||
|
||||
if($r) {
|
||||
@@ -333,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,12 @@ class Item extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 ";
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
|
||||
|
||||
$i = null;
|
||||
|
||||
@@ -167,7 +172,12 @@ class Item extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 ";
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
|
||||
|
||||
$i = null;
|
||||
|
||||
@@ -735,10 +745,10 @@ class Item extends Controller {
|
||||
|
||||
if($parent_item) {
|
||||
$acl->set($parent_item);
|
||||
$private = intval($acl->is_private() || $parent_item['item_private']);
|
||||
$public_policy = $parent_item['public_policy'];
|
||||
$owner_hash = $parent_item['owner_xchan'];
|
||||
$webpage = $parent_item['item_type'];
|
||||
$private = intval($parent_item['item_private']);
|
||||
$public_policy = $parent_item['public_policy'];
|
||||
$owner_hash = $parent_item['owner_xchan'];
|
||||
$webpage = $parent_item['item_type'];
|
||||
}
|
||||
|
||||
if((! $allow_empty) && (! strlen($body))) {
|
||||
@@ -821,18 +831,16 @@ class Item extends Controller {
|
||||
// and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
|
||||
// we may need virtual or template classes to implement the possible alternatives
|
||||
|
||||
$summary = cleanup_bbcode($summary);
|
||||
$body = cleanup_bbcode($body);
|
||||
|
||||
// Look for tags and linkify them
|
||||
|
||||
$results = linkify_tags($summary, ($uid) ? $uid : $profile_uid);
|
||||
$results = linkify_tags($body, ($uid) ? $uid : $profile_uid);
|
||||
|
||||
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'];
|
||||
|
||||
@@ -40,7 +40,7 @@ class Magic extends Controller {
|
||||
goaway($dest);
|
||||
}
|
||||
|
||||
$basepath = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '');
|
||||
$basepath = $parsed['scheme'] . '://' . $parsed['host'] . (isset($parsed['port']) ? ':' . $parsed['port'] : '');
|
||||
$owapath = SConfig::get($basepath,'system','openwebauth', $basepath . '/owa');
|
||||
|
||||
// This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating.
|
||||
@@ -110,6 +110,7 @@ class Magic extends Controller {
|
||||
$headers['(request-target)'] = 'post ' . '/owa';
|
||||
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
|
||||
$redirects = 0;
|
||||
$x = z_post_url($owapath,$data,$redirects,[ 'headers' => $headers ]);
|
||||
logger('owa fetch returned: ' . print_r($x,true),LOGGER_DATA);
|
||||
if ($x['success']) {
|
||||
|
||||
@@ -5,18 +5,18 @@ namespace Zotlabs\Module;
|
||||
class Manage extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
if((! get_account_id()) || ($_SESSION['delegate'])) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
nav_set_selected('Channel Manager', 'settings/manage');
|
||||
|
||||
|
||||
require_once('include/security.php');
|
||||
|
||||
|
||||
$change_channel = ((argc() > 1) ? intval(argv(1)) : 0);
|
||||
|
||||
|
||||
if((argc() > 2) && (argv(2) === 'default')) {
|
||||
$r = q("select channel_id from channel where channel_id = %d and channel_account_id = %d limit 1",
|
||||
intval($change_channel),
|
||||
@@ -31,7 +31,7 @@ class Manage extends \Zotlabs\Web\Controller {
|
||||
goaway(z_root() . '/manage');
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($change_channel) {
|
||||
|
||||
$r = change_channel($change_channel);
|
||||
@@ -45,29 +45,29 @@ class Manage extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
goaway(z_root());
|
||||
}
|
||||
|
||||
|
||||
$channels = null;
|
||||
|
||||
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and channel_removed = 0 order by channel_name ",
|
||||
intval(get_account_id())
|
||||
);
|
||||
|
||||
|
||||
$account = \App::get_account();
|
||||
|
||||
|
||||
if($r && count($r)) {
|
||||
$channels = $r;
|
||||
for($x = 0; $x < count($channels); $x ++) {
|
||||
$channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']);
|
||||
$channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : '');
|
||||
$channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : '');
|
||||
$channels[$x]['default_links'] = '1';
|
||||
|
||||
|
||||
|
||||
|
||||
$c = q("SELECT id, item_wall FROM item
|
||||
WHERE item_unseen = 1 and uid = %d " . item_normal(),
|
||||
intval($channels[$x]['channel_id'])
|
||||
);
|
||||
|
||||
if($c) {
|
||||
|
||||
if($c) {
|
||||
foreach ($c as $it) {
|
||||
if(intval($it['item_wall']))
|
||||
$channels[$x]['home'] ++;
|
||||
@@ -75,25 +75,25 @@ class Manage extends \Zotlabs\Web\Controller {
|
||||
$channels[$x]['network'] ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
|
||||
intval($channels[$x]['channel_id'])
|
||||
);
|
||||
|
||||
|
||||
if($intr)
|
||||
$channels[$x]['intros'] = intval($intr[0]['total']);
|
||||
|
||||
|
||||
|
||||
|
||||
$mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
|
||||
intval($channels[$x]['channel_id']),
|
||||
dbesc($channels[$x]['channel_hash'])
|
||||
);
|
||||
|
||||
|
||||
if($mails)
|
||||
$channels[$x]['mail'] = intval($mails[0]['total']);
|
||||
|
||||
|
||||
|
||||
|
||||
$events = q("SELECT etype, dtstart, adjust FROM event
|
||||
WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
|
||||
ORDER BY dtstart ASC ",
|
||||
@@ -101,7 +101,7 @@ class Manage extends \Zotlabs\Web\Controller {
|
||||
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')),
|
||||
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
|
||||
);
|
||||
|
||||
|
||||
if($events) {
|
||||
$channels[$x]['all_events'] = count($events);
|
||||
|
||||
@@ -128,7 +128,7 @@ class Manage extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0",
|
||||
intval(get_account_id())
|
||||
@@ -140,23 +140,23 @@ class Manage extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
$channel_usage_message = '';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$create = array( 'new_channel', t('Create a new channel'), t('Create New'));
|
||||
|
||||
|
||||
$delegates = null;
|
||||
|
||||
if(local_channel()) {
|
||||
$delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where
|
||||
$delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where
|
||||
abook_channel = %d and abook_xchan in ( select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'delegate' and v = '1' )",
|
||||
intval(local_channel()),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if($delegates) {
|
||||
for($x = 0; $x < count($delegates); $x ++) {
|
||||
$delegates[$x]['link'] = 'magic?f=&bdest=' . bin2hex($delegates[$x]['xchan_url'])
|
||||
$delegates[$x]['link'] = 'magic?f=&bdest=' . bin2hex($delegates[$x]['xchan_url'] . '?zid=' . get_my_address() . '&delegate=' . urlencode($delegates[$x]['xchan_addr']))
|
||||
. '&delegate=' . urlencode($delegates[$x]['xchan_addr']);
|
||||
$delegates[$x]['channel_name'] = $delegates[$x]['xchan_name'];
|
||||
$delegates[$x]['delegate'] = 1;
|
||||
@@ -165,7 +165,7 @@ class Manage extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
$delegates = null;
|
||||
}
|
||||
|
||||
|
||||
$o = replace_macros(get_markup_template('channels.tpl'), array(
|
||||
'$header' => t('Channel Manager'),
|
||||
'$msg_selected' => t('Current Channel'),
|
||||
@@ -181,9 +181,9 @@ class Manage extends \Zotlabs\Web\Controller {
|
||||
'$delegated_desc' => t('Delegated Channel'),
|
||||
'$delegates' => $delegates
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,13 +20,15 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?']) || strpos($_GET['search'], 'https://') === 0)
|
||||
goaway('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');
|
||||
if($network_options)
|
||||
goaway('network' . '?f=&' . $network_options);
|
||||
goaway(z_root() . '/network?f=&' . $network_options);
|
||||
}
|
||||
|
||||
$channel = App::get_channel();
|
||||
@@ -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)
|
||||
);
|
||||
|
||||
@@ -876,7 +876,7 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
$prevlink = '';
|
||||
$nextlink = '';
|
||||
|
||||
if($_GET['order'] === 'posted')
|
||||
if(isset($_GET['order']) && $_GET['order'] === 'posted')
|
||||
$order = 'ASC';
|
||||
else
|
||||
$order = 'DESC';
|
||||
@@ -901,8 +901,8 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
|
||||
$nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
|
||||
$prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['hash'] . (($order == 'ASC') ? '?f=&order=posted' : '');
|
||||
$nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['hash'] . (($order == 'ASC') ? '?f=&order=posted' : '');
|
||||
}
|
||||
|
||||
|
||||
@@ -987,7 +987,7 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$tags = array();
|
||||
if($link_item['term']) {
|
||||
if(x($link_item, 'term')) {
|
||||
$cnt = 0;
|
||||
foreach($link_item['term'] as $t) {
|
||||
$tags[$cnt] = array(0 => format_term_for_display($t));
|
||||
|
||||
@@ -29,26 +29,28 @@ class Profile extends Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$profile = '';
|
||||
$channel = App::get_channel();
|
||||
|
||||
if (!$channel)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
if (ActivityStreams::is_as_request()) {
|
||||
$channel = channelx_by_nick($which);
|
||||
if (!$channel) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$p = Activity::encode_person($channel, true);
|
||||
as_return_and_die(['type' => 'Profile', 'describes' => $p], $channel);
|
||||
}
|
||||
|
||||
nav_set_selected('Profile');
|
||||
$profile = '';
|
||||
|
||||
if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
||||
$channel = App::get_channel();
|
||||
$which = $channel['channel_address'];
|
||||
$profile = argv(1);
|
||||
$r = q("select profile_guid from profile where id = %d and uid = %d limit 1",
|
||||
|
||||
$r = q("select profile_guid from profile where id = %d and uid = %d limit 1",
|
||||
intval($profile),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if (!$r)
|
||||
$profile = '';
|
||||
$profile = $r[0]['profile_guid'];
|
||||
@@ -80,7 +82,6 @@ class Profile extends Controller {
|
||||
|
||||
profile_load($which, $profile);
|
||||
|
||||
|
||||
}
|
||||
|
||||
function get() {
|
||||
@@ -89,11 +90,10 @@ class Profile extends Controller {
|
||||
return login();
|
||||
}
|
||||
|
||||
nav_set_selected('Profile');
|
||||
|
||||
$groups = [];
|
||||
|
||||
|
||||
$tab = 'profile';
|
||||
$o = '';
|
||||
$o = '';
|
||||
|
||||
if (!(perm_is_allowed(App::$profile['profile_uid'], get_observer_hash(), 'view_profile'))) {
|
||||
notice(t('Permission denied.') . EOL);
|
||||
|
||||
@@ -197,7 +197,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($update) {
|
||||
|
||||
$ordering = "commented";
|
||||
$ordering = get_config('system', 'pubstream_ordering', 'commented');
|
||||
|
||||
if($load) {
|
||||
if($mid) {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,54 +5,54 @@ namespace Zotlabs\Module;
|
||||
class Removeme extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
|
||||
if($_SESSION['delegate'])
|
||||
return;
|
||||
|
||||
|
||||
if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password']))))
|
||||
return;
|
||||
|
||||
|
||||
if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify']))))
|
||||
return;
|
||||
|
||||
|
||||
if($_POST['verify'] !== $_SESSION['remove_account_verify'])
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
$account = \App::get_account();
|
||||
|
||||
|
||||
|
||||
|
||||
$x = account_verify_password($account['account_email'],$_POST['qxz_password']);
|
||||
if(! ($x && $x['account']))
|
||||
return;
|
||||
|
||||
|
||||
if($account['account_password_changed'] > NULL_DATE) {
|
||||
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
|
||||
if($account['account_password_changed'] > d1) {
|
||||
if($account['account_password_changed'] > $d1) {
|
||||
notice( t('Channel removals are not allowed within 48 hours of changing the account password.') . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$global_remove = 0; //intval($_POST['global']);
|
||||
|
||||
channel_remove(local_channel(),1 - $global_remove,true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
if(! local_channel())
|
||||
goaway(z_root());
|
||||
|
||||
|
||||
$hash = random_string();
|
||||
|
||||
|
||||
$_SESSION['remove_account_verify'] = $hash;
|
||||
|
||||
|
||||
$tpl = get_markup_template('removeme.tpl');
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$basedir' => z_root(),
|
||||
@@ -63,9 +63,9 @@ class Removeme extends \Zotlabs\Web\Controller {
|
||||
// '$global' => [ 'global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network'), [ t('No'),t('Yes') ] ],
|
||||
'$submit' => t('Remove Channel')
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ class Search extends Controller {
|
||||
App::$data['search'] = escape_tags($_REQUEST['search']);
|
||||
}
|
||||
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
|
||||
if ((get_config('system', 'block_public')) || (get_config('system', 'block_public_search'))) {
|
||||
@@ -59,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()) {
|
||||
@@ -102,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);
|
||||
}
|
||||
|
||||
@@ -194,7 +193,7 @@ class Search extends Controller {
|
||||
|
||||
if (local_channel()) {
|
||||
$r = q("SELECT mid, MAX(id) as item_id from item
|
||||
WHERE ((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' AND item.deny_gid = '' AND item_private = 0 )
|
||||
WHERE ((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' AND item.deny_gid = '' AND item_private = 0 )
|
||||
OR ( item.uid = %d )) OR item.owner_xchan = '%s' )
|
||||
$item_normal
|
||||
$sql_extra
|
||||
@@ -210,7 +209,7 @@ class Search extends Controller {
|
||||
and owner_xchan in ( " . stream_perms_xchans(($observer) ? (PERMS_NETWORK | PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
||||
$pub_sql ) OR owner_xchan = '%s')
|
||||
$item_normal
|
||||
$sql_extra
|
||||
$sql_extra
|
||||
group by mid, created order by created desc $pager_sql",
|
||||
dbesc($sys['xchan_hash'])
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
@@ -109,7 +108,8 @@ class Sse extends Controller {
|
||||
echo 'data: {}';
|
||||
echo "\n\n";
|
||||
|
||||
ob_end_flush();
|
||||
if(ob_get_length() > 0)
|
||||
ob_end_flush();
|
||||
flush();
|
||||
|
||||
if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -142,11 +144,15 @@ class Sse_bs extends Controller {
|
||||
$result['network']['notifications'] = [];
|
||||
$result['network']['count'] = 0;
|
||||
|
||||
if(! self::$uid)
|
||||
if(! self::$uid) {
|
||||
$result['network']['offset'] = -1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
if(! (self::$vnotify & VNOTIFY_NETWORK))
|
||||
if(! (self::$vnotify & VNOTIFY_NETWORK)) {
|
||||
$result['network']['offset'] = -1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
$limit = intval(self::$limit);
|
||||
$offset = self::$offset;
|
||||
@@ -214,11 +220,15 @@ class Sse_bs extends Controller {
|
||||
$result['dm']['notifications'] = [];
|
||||
$result['dm']['count'] = 0;
|
||||
|
||||
if(! self::$uid)
|
||||
if(! self::$uid) {
|
||||
$result['dm']['offset'] = -1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
if(! (self::$vnotify & VNOTIFY_MAIL))
|
||||
if(! (self::$vnotify & VNOTIFY_MAIL)) {
|
||||
$result['dm']['offset'] = -1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
$limit = intval(self::$limit);
|
||||
$offset = self::$offset;
|
||||
@@ -285,11 +295,15 @@ class Sse_bs extends Controller {
|
||||
$result['home']['notifications'] = [];
|
||||
$result['home']['count'] = 0;
|
||||
|
||||
if(! self::$uid)
|
||||
if(! self::$uid) {
|
||||
$result['home']['offset'] = -1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
if(! (self::$vnotify & VNOTIFY_CHANNEL))
|
||||
if(! (self::$vnotify & VNOTIFY_CHANNEL)) {
|
||||
$result['home']['offset'] = -1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
$limit = intval(self::$limit);
|
||||
$offset = self::$offset;
|
||||
@@ -357,15 +371,19 @@ class Sse_bs extends Controller {
|
||||
$result['pubs']['notifications'] = [];
|
||||
$result['pubs']['count'] = 0;
|
||||
|
||||
if(! (self::$vnotify & VNOTIFY_PUBS))
|
||||
if(! (self::$vnotify & VNOTIFY_PUBS)) {
|
||||
$result['pubs']['offset'] = -1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
if((observer_prohibited(true))) {
|
||||
$result['pubs']['offset'] = -1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
if(! intval(get_config('system','open_pubstream',1))) {
|
||||
if(! get_observer_hash()) {
|
||||
$result['pubs']['offset'] = -1;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -686,12 +704,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 +724,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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/items.php');
|
||||
@@ -10,22 +13,22 @@ require_once('include/items.php');
|
||||
class Subthread extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$item_id = ((argc() > 2) ? notags(trim(argv(2))) : 0);
|
||||
|
||||
|
||||
if(argv(1) === 'sub')
|
||||
$activity = ACTIVITY_FOLLOW;
|
||||
elseif(argv(1) === 'unsub')
|
||||
$activity = ACTIVITY_UNFOLLOW;
|
||||
|
||||
|
||||
|
||||
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($item_id),
|
||||
intval(local_channel())
|
||||
@@ -42,7 +45,7 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
$item_id = (($i) ? $i[0]['id'] : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(! $i) {
|
||||
return;
|
||||
}
|
||||
@@ -56,37 +59,37 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
dbesc($r[0]['parent'])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if((! $item_id) || (! $r)) {
|
||||
logger('subthread: no item ' . $item_id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$item = $r[0];
|
||||
|
||||
|
||||
$owner_uid = $item['uid'];
|
||||
$observer = \App::get_observer();
|
||||
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||
|
||||
|
||||
if(! perm_is_allowed($owner_uid,$ob_hash,'post_comments'))
|
||||
return;
|
||||
|
||||
|
||||
$sys = get_sys_channel();
|
||||
|
||||
|
||||
$owner_uid = $item['uid'];
|
||||
$owner_aid = $item['aid'];
|
||||
|
||||
|
||||
// if this is a "discover" item, (item['uid'] is the sys channel),
|
||||
// fallback to the item comment policy, which should've been
|
||||
// respected when generating the conversation thread.
|
||||
// Even if the activity is rejected by the item owner, it should still get attached
|
||||
// to the local discover conversation on this site.
|
||||
|
||||
// to the local discover conversation on this site.
|
||||
|
||||
if(($owner_uid != $sys['channel_id']) && (! perm_is_allowed($owner_uid,$observer['xchan_hash'],'post_comments'))) {
|
||||
notice( t('Permission denied') . EOL);
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($item['owner_xchan'])
|
||||
);
|
||||
@@ -94,7 +97,7 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
$thread_owner = $r[0];
|
||||
else
|
||||
killme();
|
||||
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($item['author_xchan'])
|
||||
);
|
||||
@@ -102,50 +105,32 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
$item_author = $r[0];
|
||||
else
|
||||
killme();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$uuid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
|
||||
|
||||
|
||||
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
|
||||
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
|
||||
|
||||
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
|
||||
|
||||
$body = $item['body'];
|
||||
|
||||
$obj = json_encode(array(
|
||||
'type' => $objtype,
|
||||
'id' => $item['mid'],
|
||||
'parent' => (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']),
|
||||
'link' => $links,
|
||||
'title' => $item['title'],
|
||||
'content' => $item['body'],
|
||||
'created' => $item['created'],
|
||||
'edited' => $item['edited'],
|
||||
'author' => array(
|
||||
'name' => $item_author['xchan_name'],
|
||||
'address' => $item_author['xchan_addr'],
|
||||
'guid' => $item_author['xchan_guid'],
|
||||
'guid_sig' => $item_author['xchan_guid_sig'],
|
||||
'link' => array(
|
||||
array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']),
|
||||
array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])),
|
||||
),
|
||||
));
|
||||
|
||||
|
||||
$obj = Activity::fetch_item( [ 'id' => $item['mid'] ] );
|
||||
|
||||
if(! intval($item['item_thread_top']))
|
||||
$post_type = 'comment';
|
||||
|
||||
$post_type = 'comment';
|
||||
|
||||
if($activity === ACTIVITY_FOLLOW)
|
||||
$bodyverb = t('%1$s is following %2$s\'s %3$s');
|
||||
if($activity === ACTIVITY_UNFOLLOW)
|
||||
$bodyverb = t('%1$s stopped following %2$s\'s %3$s');
|
||||
|
||||
|
||||
$arr = array();
|
||||
|
||||
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = $mid;
|
||||
$arr['aid'] = $owner_aid;
|
||||
@@ -161,35 +146,35 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
$arr['item_wall'] = 1;
|
||||
else
|
||||
$arr['item_wall'] = 0;
|
||||
|
||||
|
||||
$ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]';
|
||||
$alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
|
||||
$plink = '[zrl=' . z_root() . '/display/' . gen_link_id($item['mid']) . ']' . $post_type . '[/zrl]';
|
||||
|
||||
|
||||
$arr['body'] = sprintf( $bodyverb, $alink, $ulink, $plink );
|
||||
|
||||
|
||||
$arr['verb'] = $activity;
|
||||
$arr['obj_type'] = $objtype;
|
||||
$arr['obj'] = $obj;
|
||||
|
||||
$arr['obj'] = json_encode($obj);
|
||||
|
||||
$arr['allow_cid'] = $item['allow_cid'];
|
||||
$arr['allow_gid'] = $item['allow_gid'];
|
||||
$arr['deny_cid'] = $item['deny_cid'];
|
||||
$arr['deny_gid'] = $item['deny_gid'];
|
||||
|
||||
$post = item_store($arr);
|
||||
|
||||
$post = item_store($arr);
|
||||
$post_id = $post['item_id'];
|
||||
|
||||
|
||||
$arr['id'] = $post_id;
|
||||
|
||||
|
||||
call_hooks('post_local_end', $arr);
|
||||
|
||||
|
||||
killme();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -19,7 +19,7 @@ class Zotfeed extends Controller {
|
||||
killme();
|
||||
}
|
||||
|
||||
$channel = ((argv(1)) ? channelx_by_nick(argv(1)) : get_sys_channel());
|
||||
$channel = channelx_by_nick(argv(1));
|
||||
if (!$channel) {
|
||||
killme();
|
||||
}
|
||||
@@ -120,45 +120,5 @@ class Zotfeed extends Controller {
|
||||
|
||||
as_return_and_die($ret, $channel);
|
||||
}
|
||||
|
||||
/*
|
||||
$result = array('success' => false);
|
||||
|
||||
$mindate = (($_REQUEST['mindate']) ? datetime_convert('UTC','UTC',$_REQUEST['mindate']) : '');
|
||||
if(! $mindate)
|
||||
$mindate = datetime_convert('UTC','UTC', 'now - 14 days');
|
||||
|
||||
if(observer_prohibited()) {
|
||||
$result['message'] = 'Public access denied';
|
||||
json_return_and_die($result);
|
||||
}
|
||||
|
||||
$observer = App::get_observer();
|
||||
|
||||
logger('observer: ' . get_observer_hash(), LOGGER_DEBUG);
|
||||
|
||||
$channel_address = ((argc() > 1) ? argv(1) : '');
|
||||
if($channel_address) {
|
||||
$r = q("select channel_id, channel_name from channel where channel_address = '%s' and channel_removed = 0 limit 1",
|
||||
dbesc(argv(1))
|
||||
);
|
||||
}
|
||||
else {
|
||||
$x = get_sys_channel();
|
||||
if($x)
|
||||
$r = array($x);
|
||||
$mindate = datetime_convert('UTC','UTC', 'now - 14 days');
|
||||
}
|
||||
if(! $r) {
|
||||
$result['message'] = 'Channel not found.';
|
||||
json_return_and_die($result);
|
||||
}
|
||||
|
||||
logger('zotfeed request: ' . $r[0]['channel_name'], LOGGER_DEBUG);
|
||||
$result['project'] = 'Hubzilla';
|
||||
$result['messages'] = zot_feed($r[0]['channel_id'],$observer['xchan_hash'],array('mindate' => $mindate));
|
||||
$result['success'] = true;
|
||||
json_return_and_die($result);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
37
boot.php
37
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' );
|
||||
define ( 'STD_VERSION', '5.6.1' );
|
||||
define ( 'ZOT_REVISION', '6.0' );
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1243 );
|
||||
define ( 'DB_UPDATE_VERSION', 1245 );
|
||||
|
||||
define ( 'PROJECT_BASE', __DIR__ );
|
||||
|
||||
@@ -1709,21 +1709,24 @@ function login($register = false, $form_id = 'main-login', $hiddens = false, $lo
|
||||
$_SESSION['login_return_url'] = App::$query_string;
|
||||
}
|
||||
|
||||
$o .= replace_macros($tpl,array(
|
||||
$email_required = get_config('system', 'verify_email');
|
||||
$lname_label = (($email_required) ? t('Email or nickname') : t('Nickname'));
|
||||
|
||||
$o .= replace_macros($tpl, [
|
||||
'$dest_url' => $dest_url,
|
||||
'$login_page' => $login_page,
|
||||
'$logout' => t('Logout'),
|
||||
'$login' => t('Login'),
|
||||
'$remote_login' => t('Remote Authentication'),
|
||||
'$form_id' => $form_id,
|
||||
'$lname' => array('username', t('Login/Email') , '', ''),
|
||||
'$lpassword' => array('password', t('Password'), '', ''),
|
||||
'$remember_me' => array((($login_page) ? 'remember' : 'remember_me'), t('Remember me'), '', '',array(t('No'),t('Yes'))),
|
||||
'$lname' => ['username', $lname_label],
|
||||
'$lpassword' => ['password', t('Password')],
|
||||
'$remember_me' => [(($login_page) ? 'remember' : 'remember_me'), t('Remember me'), '', '', [t('No'),t('Yes')]],
|
||||
'$hiddens' => $hiddens,
|
||||
'$register' => $reg,
|
||||
'$lostpass' => t('Forgot your password?'),
|
||||
'$lostlink' => t('Password Reset'),
|
||||
));
|
||||
'$lostlink' => (($email_required) ? t('Password Reset') : ''),
|
||||
]);
|
||||
|
||||
/**
|
||||
* @hooks login_hook
|
||||
@@ -2316,13 +2319,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);
|
||||
}
|
||||
|
||||
@@ -2419,16 +2423,15 @@ function construct_page() {
|
||||
|
||||
// security headers - see https://securityheaders.io
|
||||
|
||||
if(App::get_scheme() === 'https' && App::$config['system']['transport_security_header'])
|
||||
if(App::get_scheme() === 'https' && isset(App::$config['system']['transport_security_header']) && intval(App::$config['system']['transport_security_header']) == 1)
|
||||
header("Strict-Transport-Security: max-age=31536000");
|
||||
|
||||
if(isset(App::$config['system']['content_security_policy'])) {
|
||||
if(isset(App::$config['system']['content_security_policy']) && intval(App::$config['system']['content_security_policy']) == 1) {
|
||||
$cspsettings = [
|
||||
'script-src' => [ "'self'", "'unsafe-inline'", "'unsafe-eval'" ],
|
||||
'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 +2463,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>
|
||||
@@ -1,7 +1,7 @@
|
||||
<dl class="dl-horizontal">
|
||||
<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.
|
||||
Statystyki kolejki pokazują, ile wpisów znajduje się w kolejce w celu dostarczenia
|
||||
ich do innych portali. Priorytet jest zwią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
|
||||
wykrywaniem danych identyfikacyjnych, Hubzilla zawiera mechanizm tworzenia
|
||||
Aby ułatwić udostępnianie prywatnych zasobów osobom niebędących członkami
|
||||
tego portalu lub sfederyzowanych portali (hubów) i zapewnić zabezpieczone
|
||||
wykrywaniem danych identyfikacyjnych, Hubzilla posiada 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>
|
||||
|
||||
@@ -87,6 +87,7 @@ Options are:
|
||||
[*= system.proc_run_use_exec ] If 1, use the exec system call in proc_run to run background tasks. By default we use proc_open and proc_close. On some (currently rare) systems this does not work well.
|
||||
[*= system.projecthome ] Display the project page on your home page for logged out viewers.
|
||||
[*= system.projecthome ] Set the project homepage as the homepage of your hub. (Obsolete)
|
||||
[*= system.pubstream_ordering ] Set pubstream ordering. Possible values 'commented' (default), 'created' and 'edited'.
|
||||
[*= system.register_link ] path to direct to from the "register" link on the login form. On closed sites this will direct to 'pubsites'. For open sites it will normally redirect to 'register' but you may change this to a custom site page offering subscriptions or whatever.
|
||||
[*= system.reserved_channels ] Don't allow members to register channels with this comma separated list of names (no spaces)
|
||||
[*= system.sellpage ] A URL shown in the public sites list to sell your hub - display service classes, etc.
|
||||
|
||||
@@ -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 (portale 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 portali. Ogranicza to dostęp tylko do kanałów w portalipodłączonych do tego serwera katalogowego.
|
||||
|
||||
##Instrukcje dotyczące konfigurowania jednego portalu jako katalogu podstawowego dla wielu portali prywatnych.##
|
||||
***
|
||||
|
||||
|
||||
* Na portalu , 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, na każdym portalu (w tym na serwerze katalogowym), w terminalu, przejdź do folderu z kodem $Projectname i uruchom 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 portalu
|
||||
|
||||
* Na koniec, dla każdego portalu "klienckiego", uruchom (z terminala):
|
||||
|
||||
`util/config system directory_server https://theaddressofyourdirectoryserver.com`
|
||||
|
||||
***
|
||||
Teraz, gdy przeglądasz katalog każdego portalu, powinien on pokazywać tylko kanały, które istnieją w portalach ustawionej domeny katalogowej. Do tej pory testowałem to z dwoma portalami i wydaje się, że działa dobrze.
|
||||
Kanały utworzone w każdym portalu są odzwierciedlane w katalogu głównym, a następnie w katalogu wszystkich portali klienckich
|
||||
|
||||
##Problemy##
|
||||
***
|
||||
|
||||
Kiedy tworzyłem pierwszy portal, 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 sieci. Usunąłem je z tabeli xchan i wydaje się, że rozwiązało to problem.
|
||||
@@ -1,56 +1,54 @@
|
||||
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 albo `pl` dla polskiego.
|
||||
|
||||
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.
|
||||
|
||||
@@ -65,10 +63,8 @@ Zakładając, że chcesz przetłumaczyć niemiecką wersję umieszczoną pliku
|
||||
Narzędzia
|
||||
---------
|
||||
|
||||
Oprócz skryptu po2php, jest jeszcze w katalogu "util" w drzewie źródłowym $Projectname
|
||||
kilka narzędzi do tłumaczenia. Jeśli tylko chcesz przetłumacz $Projectname na inny
|
||||
język, którego nie potrzebujesz najbardziej, ale da Ci to wyobrażenie o procesie
|
||||
tłumaczenia $Projectname.
|
||||
Oprócz skryptu po2php, jest jeszcze w katalogu "util" w drzewie źródłowym $Projectname kilka narzędzi do tłumaczenia. Jeśli tylko chcesz przetłumacz $Projectname na inny język, którego nie potrzebujesz najbardziej, ale da Ci to wyobrażenie o procesie
|
||||
tłumaczenia $Projectname.
|
||||
|
||||
Więcej informacji można znaleźć w pliku utils/README.
|
||||
|
||||
|
||||
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,8 @@
|
||||
[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 Hubzilla to bezpłatny i otwartoźródłowy zestaw aplikacji i usług internetowych, które można wdrożyć na własnym serwerze internetowym jako samodzielny portal społecznościowy, zwanym też "hubem". Portal ten może łączyć się z innymi portalami tego typu, tworząc sfederowaną sieć społecznościową.
|
||||
$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 komunikować się i publikować treści w swoich "kanałach" z możliwością bardzo szczegółowej kontroli dostępu. Kanały są zabezpieczonymi kryptograficznie tożsamościami internetowymi, zapewniającymi uwierzytelnianie użytkowników niezależnie od portali na których są hostowane. 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 portalu, 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 +10,25 @@ 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 portalu[/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, wymagającą niewiele więcej niż [url=https://framagit.org/$Projectname/core/blob/master/install/INSTALL.txt]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
|
||||
[*= portal, hub ([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ć portali, które wymieniają między sobą informacje za pomocą protokołu Zot. Nie są to tylko portale oparte na $Projectname, ale wszystkie portale implementujące 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 portalach. 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 portali. 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 portalu 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 (portalu), ś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 portalach w sieci Zot, w sposób zsynchronizowany. Na tych portalach 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 portalami i domenami internetowymi. Tożsamość nomadyczna zapewnia prawdziwą własność tożsamości internetową, ponieważ tożsamości kontrolowane przez konto na portalu nie są ściśle związane z tym portalem. Portal 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 +46,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 +65,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 +85,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 +93,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 portal $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 portali $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,52 +127,52 @@ 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 portalem, 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 portalu 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 portalu $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 portal, na którym oparta jest tożsamość, nagle przestanie działać? Bez sklonowania tożsamości członek tego portalu nie będzie mógł się komunikować, dopóki portal 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 portalu nie może już sobie pozwolić na opłacanie swojego bezpłatnego i publicznego portalu $Projectname. Zapowiada, że portal 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? Operator Twojego portalu 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 portalach, 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ŚĆ".
|
||||
|
||||
[h4]Wiele profili[/h4]
|
||||
Można utworzyć dowolną liczbę profili zawierających różne informacje, które mogą być widoczne dla niektórych Twoich kontaktów i znajomych. Profil "domyślny" może być widoczny dla każdego i może zawierać ograniczone informacje, a więcej informacji jest dostępnych dla wybranych grup lub osób. Oznacza to, że profil (i zawartość witryny), który widzą Twoi znajomi pijący piwo, może być inny niż to, co widzą Twoi współpracownicy, a także zupełnie inny niż to, co jest widoczne dla ogółu społeczeństwa.
|
||||
Można utworzyć dowolną liczbę profili zawierających różne informacje, które mogą być widoczne dla niektórych Twoich kontaktów i znajomych. Profil "domyślny" może być widoczny dla każdego i zawierać tylko ograniczone informacje o Tobie. Natomiast dodatkowe profile, dostępne dla wybranych grup lub osób, mogą juz zawierać dodatkowe informacje. Oznacza to, że profil (i przypisane mu treści), który widzą Twoi znajomi pijący piwo, może być inny niż to, co widzą Twoi współpracownicy, a także zupełnie inny niż to, co jest widoczne dla ogółu internautów.
|
||||
|
||||
[h4]Kopia zapasowa konta[/h4]
|
||||
|
||||
$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) portalu kanału, czy w innym portalu, 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 postronne - najlepiej jak potrafimy. Administratorzy portali 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 portali.
|
||||
|
||||
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 portali podlegają lokalnemu prawodawstwu i MOGĄ usunąć budzące zastrzeżenia treści ze swojego portalu. Każdy może zostać administratorem portalu, 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 nazywane "platformą $Projectname", jest oprogramowaniem do budowania portali internetowych zdolnych do tworzenia zdecenralizowanych sieci społecznościowych. Poszczególne portale są węzłami tej sieci (ang. *hubs*) i mogą łączyć się z innymi federacyjnymi sieciami społecznościowymi, tworząc razem globalną sieć społecznosciową, zwaną "Fediverse".
|
||||
|
||||
**hub** (ang. *hub*)
|
||||
**portal, hub** (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.
|
||||
Implementacja $Projectname na serwerze internetowym. Stanowi serwis internetowy sieci WWW. Jest on dostarczany przez **operatora portalu** i może być publiczny lub prywatny, płatnu lub bezpłatny.
|
||||
|
||||
*administrator huba**
|
||||
*administrator portalu**
|
||||
|
||||
Operator systemu pojedynczego huba.
|
||||
Osoba wyznaczona przez operator portalu do zarządzania portalem.
|
||||
|
||||
[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 portali 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 portalu 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 portalu, 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 portalu. 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 Twój portal. Jeśli chcesz mieć pełną kontrolę nad swoją prywatnością i bezpieczeństwem, powinieneś uruchomić własny portal 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 portalom 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 portal. Oznacza to, że wszystkie kanały i treści na tym portalu nie są publiczne ani widoczne dla świata zewnętrznego. To jest coś, co może zrobić tylko administrator portalu. 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 portali MOGĄ cenzurować wszelkie treści, które pojawiają się w ich portalu, aby zachować zgodność z lokalnym prawem, a nawet osobistym osądem. Ich decyzja jest ostateczna. Jeśli masz problemy z jakimkolwiek administratorem portali, 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 portalu, 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 portalu). Mimo to. możesz stwierdzić, że Twoje treści są zablokowane w niektórych portalach, ale $Projectname jako sieć nie może w ogó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.
|
||||
W $Projectname ZALECA się, aby administratorzy portali 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 portalu, 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.
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[size=large][b]Konta, profile i kanały[/b][/size]
|
||||
|
||||
Po zarejestrowaniu [i]konta[/i], trzeba również utworzyć [i]profil[/i] i [i]kanał[/i].
|
||||
Po zarejestrowaniu [i]konta[/i], trzeba również utworzyć [i]profil[/i] i [i]kanał[/i]. Na wielu portalach $Projectname Twój kanał jest zakładany automatycznie, ale to i tak wymaga Twojej interwencji. Profil będzie wymagał uzupełnienia lub poprawienia danych, podobnie jak automatycznie założony kanał.
|
||||
|
||||
[b]Konto[/b]
|
||||
W serwisie &Projectname masz [i]jedno[/i] konto. Składa się z Twojego konta e-mail i hasła. Za pomocą swojego konta uzyskujesz dostęp do swojego profilu i kanału.
|
||||
Na portalu $Projectname masz [i]jedno[/i] konto. Składa się z Twojego adresu e-mail i hasła. Za pomocą swojego konta uzyskujesz dostęp do swojego profilu i kanału.
|
||||
|
||||
[i]Pomyśl o swoim koncie jak o sposobie uwierzytelniania w jednym serwisie $Projectname. Pozwala to na takie rzeczy, jak tworzenie profili i kanałów, za pomocą których możesz łączyć się z innymi osobami.[/i]
|
||||
[i]Pomyśl o swoim koncie jak o sposobie uwierzytelniania na którymkolwiek portalu $Projectname. Pozwala ono na takie rzeczy, jak tworzenie profili i kanałów, za pomocą których możesz łączyć się z innymi osobami.[/i]
|
||||
|
||||
[b]Profil[/b]
|
||||
Z pewnością masz już doświadczenie w rejestrowaniu się w jakichś usługach internetowych, takich jak fora lub społeczności internetowe. We wszystkich przypadkach trzeba było podać pewne informacje o sobie, takie jak data urodzenia, kraj, wiek i upodobania. [observer=1]Jeśli chcesz, możesz zobaczyć swój profil tutaj: [baseurl]/profile/[observer.webname] i edytować go, klikając ikonę ołówka obok swojego awatara.[/observer]
|
||||
@@ -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]. Zostaje on przyporządkowany do domyślnego profilu. Podobnie jak w przypadku profili, możesz mieć kilka kanałów (jeśli parametry konta to dopuszczają). Na początku może to być nieco zagmatwane, ale wyjaśnijmy to. Masz już jeden kanał. Możesz używać go publicznie, aby komunikować się z osobami 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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user