Compare commits
452 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7e79f7423 | ||
|
|
589af1f9ee | ||
|
|
e7f25b8466 | ||
|
|
2100441b54 | ||
|
|
082826ee44 | ||
|
|
93ad3eb6f1 | ||
|
|
177209b5e9 | ||
|
|
47d80df81c | ||
|
|
3d6fa049da | ||
|
|
16738dfe7f | ||
|
|
c28ba4be37 | ||
|
|
8bcdc24fcb | ||
|
|
b36eb9a91c | ||
|
|
989fbe70cd | ||
|
|
7bb94f9993 | ||
|
|
1297c8d2ae | ||
|
|
ed28ef185e | ||
|
|
9d97cc2a1d | ||
|
|
23acf02d58 | ||
|
|
60311eb04b | ||
|
|
b9a8b9e47b | ||
|
|
b7bac45427 | ||
|
|
7d05b8e5fd | ||
|
|
d5ae9aedc4 | ||
|
|
1b216e6019 | ||
|
|
83256c9ccd | ||
|
|
9f029336ca | ||
|
|
95476cf33c | ||
|
|
bf7c96807a | ||
|
|
d4a6aa7801 | ||
|
|
b767bda410 | ||
|
|
a39d436f9f | ||
|
|
50dbe1e62d | ||
|
|
be81a40b2b | ||
|
|
bbcb237f5b | ||
|
|
33be244d8a | ||
|
|
ca75619518 | ||
|
|
82acfb75a1 | ||
|
|
fc9e6d289a | ||
|
|
6838342d62 | ||
|
|
69b25e490e | ||
|
|
b8d7647c48 | ||
|
|
989443a569 | ||
|
|
c50a311ff3 | ||
|
|
b37e5a426a | ||
|
|
5e76318e44 | ||
|
|
8ed3971ef0 | ||
|
|
c2b6f0bc28 | ||
|
|
2c42daf609 | ||
|
|
8e2446a2fc | ||
|
|
e9b2dacb61 | ||
|
|
3df5d854b8 | ||
|
|
7d8c6cb9ed | ||
|
|
f123809d29 | ||
|
|
7abcdd34af | ||
|
|
ead56c59e2 | ||
|
|
19a8dfaa5c | ||
|
|
fa45ea1d84 | ||
|
|
8789edb65d | ||
|
|
b6abc034cf | ||
|
|
c92ea70453 | ||
|
|
07eee20525 | ||
|
|
6c9130be46 | ||
|
|
51f00cda92 | ||
|
|
7973567a7c | ||
|
|
b81b18814e | ||
|
|
bbfe71b0c6 | ||
|
|
7404183830 | ||
|
|
43aea3ce38 | ||
|
|
cbaf4b7536 | ||
|
|
570d84c031 | ||
|
|
9eeccc087d | ||
|
|
7404a8ec1a | ||
|
|
bfae86bdb6 | ||
|
|
66f6a1d186 | ||
|
|
17a4aa983e | ||
|
|
2a0a06d74a | ||
|
|
ccaa93655a | ||
|
|
65bc363685 | ||
|
|
293d411efb | ||
|
|
2a287e6def | ||
|
|
d96f4340e8 | ||
|
|
d3cbbe029c | ||
|
|
a1ccacb825 | ||
|
|
b04915161b | ||
|
|
8cb968c4b0 | ||
|
|
f645c6f3a5 | ||
|
|
4c1c690816 | ||
|
|
537a7cf03d | ||
|
|
662e8f8a4c | ||
|
|
7397348b9c | ||
|
|
5c43013692 | ||
|
|
908875a052 | ||
|
|
41ce2da080 | ||
|
|
6add6ce79b | ||
|
|
0fe9c029ab | ||
|
|
a6522b34c7 | ||
|
|
229f99fe6b | ||
|
|
bdc269d445 | ||
|
|
ff63132a32 | ||
|
|
e7fb22edc1 | ||
|
|
3c59303b68 | ||
|
|
fb4504c5a3 | ||
|
|
db22578c16 | ||
|
|
300727b8cf | ||
|
|
448fb14fc4 | ||
|
|
c42e8613e5 | ||
|
|
12de30a2b1 | ||
|
|
3d019fa2dd | ||
|
|
d5aeb13601 | ||
|
|
230f7ab6d4 | ||
|
|
d71dd21abc | ||
|
|
0d00b72569 | ||
|
|
00f6deb9bd | ||
|
|
cce5054aec | ||
|
|
544ef3bc58 | ||
|
|
124cc43962 | ||
|
|
4237dd457e | ||
|
|
88ebbd90d8 | ||
|
|
298acb9645 | ||
|
|
c4f4edd743 | ||
|
|
258a4e5627 | ||
|
|
e1400e5745 | ||
|
|
593688d539 | ||
|
|
aed6823051 | ||
|
|
96f9e51546 | ||
|
|
161ea6d51f | ||
|
|
88e755037b | ||
|
|
cde706748a | ||
|
|
3e833a5bcd | ||
|
|
475a39ff90 | ||
|
|
2dd2b755f1 | ||
|
|
a6516341c5 | ||
|
|
9a70c3c275 | ||
|
|
5998445841 | ||
|
|
d9c39d0c41 | ||
|
|
4038b78377 | ||
|
|
dce8516da4 | ||
|
|
d439dee736 | ||
|
|
295c08fcf3 | ||
|
|
efa11cbc74 | ||
|
|
4a8e222763 | ||
|
|
75b9c7d6b8 | ||
|
|
d1648fb258 | ||
|
|
34cda095fe | ||
|
|
dad7bc82c3 | ||
|
|
0ee65ee954 | ||
|
|
ae0780fe3f | ||
|
|
d2a65ab1be | ||
|
|
f4516826ef | ||
|
|
b894380f86 | ||
|
|
b48a9d3f75 | ||
|
|
21b398252a | ||
|
|
80e03268fd | ||
|
|
135b3cf1ef | ||
|
|
b9e083da61 | ||
|
|
74aa446190 | ||
|
|
0d7548a381 | ||
|
|
428b2cca21 | ||
|
|
28a316f73f | ||
|
|
0532d639c2 | ||
|
|
c17717c5db | ||
|
|
8b00913579 | ||
|
|
cf95c4878d | ||
|
|
4958e3b42c | ||
|
|
cc3edeb6f5 | ||
|
|
20c296ce53 | ||
|
|
5ccbcb44f7 | ||
|
|
adcf28af7c | ||
|
|
5b206cd4a7 | ||
|
|
1eb70b66d8 | ||
|
|
3c1ff1fc63 | ||
|
|
d711f2ad4c | ||
|
|
ae8a1c992a | ||
|
|
580d3db5a8 | ||
|
|
042cc96968 | ||
|
|
d177043c9f | ||
|
|
4c1e2c2dd8 | ||
|
|
7dcb0cc11b | ||
|
|
837d9a4df0 | ||
|
|
ec1d5ead93 | ||
|
|
f485ed174d | ||
|
|
e8560d56f5 | ||
|
|
3a937fb969 | ||
|
|
c1aa96ebf7 | ||
|
|
17e012afc6 | ||
|
|
1c6796f907 | ||
|
|
f2c73c0f45 | ||
|
|
78492d0037 | ||
|
|
2b08519f5a | ||
|
|
c86b35da70 | ||
|
|
b2003e2c3c | ||
|
|
8a08cceccb | ||
|
|
9284b60a79 | ||
|
|
b69f8a3f29 | ||
|
|
8ea7c08f43 | ||
|
|
78197aa625 | ||
|
|
fcb065bcb2 | ||
|
|
3940fa5659 | ||
|
|
697fbf33c5 | ||
|
|
901785663e | ||
|
|
9e4ff8ce25 | ||
|
|
5f1b2b4bf7 | ||
|
|
271d280c91 | ||
|
|
8f708fef9c | ||
|
|
38de059156 | ||
|
|
f0b40ac15e | ||
|
|
5c47c9ed95 | ||
|
|
dafac11aaa | ||
|
|
1fc81457a1 | ||
|
|
0d47bb6878 | ||
|
|
f6f7e7e8d2 | ||
|
|
483d450af4 | ||
|
|
decc14c324 | ||
|
|
1134be8d30 | ||
|
|
fb65c54123 | ||
|
|
fe803135d8 | ||
|
|
908ebed9fd | ||
|
|
bdb6b0d237 | ||
|
|
73a0866ac4 | ||
|
|
e6b1b20565 | ||
|
|
e40ea62c7c | ||
|
|
7864579b1e | ||
|
|
b62eb665c5 | ||
|
|
c72716eca7 | ||
|
|
530d816df6 | ||
|
|
23c47f78ea | ||
|
|
4a4c43bb2c | ||
|
|
0159b631fc | ||
|
|
e74361c4db | ||
|
|
21299c6fc1 | ||
|
|
eec42d3bb3 | ||
|
|
bd049eddd4 | ||
|
|
e762347080 | ||
|
|
53ad04cdc4 | ||
|
|
148c3f9dc5 | ||
|
|
6f1188f44f | ||
|
|
78868314a7 | ||
|
|
dc2f293089 | ||
|
|
c7a0526428 | ||
|
|
498c021aec | ||
|
|
5ee133843f | ||
|
|
9ad2902add | ||
|
|
ef75d27afb | ||
|
|
965c51c2d4 | ||
|
|
5a6b14f878 | ||
|
|
de9a7f0fa9 | ||
|
|
3009c88d24 | ||
|
|
f3fa2d853a | ||
|
|
a982aecd5b | ||
|
|
52bd27a028 | ||
|
|
e5e16da8cb | ||
|
|
b0adb70ffc | ||
|
|
2f4c619d51 | ||
|
|
6e36820b1b | ||
|
|
209d06a8f7 | ||
|
|
4a6d050e22 | ||
|
|
b033597ada | ||
|
|
89342ca9fb | ||
|
|
892f4b4182 | ||
|
|
de7891771d | ||
|
|
602768209b | ||
|
|
73b1f8fcdd | ||
|
|
e1b923ab7d | ||
|
|
bed9876d68 | ||
|
|
d184e2708f | ||
|
|
580c3f4ffe | ||
|
|
158b8aea38 | ||
|
|
d22766f458 | ||
|
|
70391243dc | ||
|
|
61eef68ff3 | ||
|
|
41cc2854c5 | ||
|
|
ec68ede79f | ||
|
|
478014f02a | ||
|
|
aff7c2d771 | ||
|
|
00dd52317a | ||
|
|
17522b31e9 | ||
|
|
163b1ee9f8 | ||
|
|
7b9a992f83 | ||
|
|
4efb258671 | ||
|
|
7532358806 | ||
|
|
13c05e7937 | ||
|
|
c6e9bca76c | ||
|
|
3706afbd01 | ||
|
|
bcd0802ea4 | ||
|
|
9360148829 | ||
|
|
a6165c00ce | ||
|
|
a5826fec25 | ||
|
|
839c6668cf | ||
|
|
e9a9fc5050 | ||
|
|
426668cd2e | ||
|
|
926d7c56a6 | ||
|
|
9934dbfe69 | ||
|
|
b6314c109d | ||
|
|
f8955f90b8 | ||
|
|
9248fc96b3 | ||
|
|
2875ee2423 | ||
|
|
36f707b25e | ||
|
|
2a05bd9ed6 | ||
|
|
b7db9944ec | ||
|
|
86f7d08483 | ||
|
|
1358a81c32 | ||
|
|
09ad48c12b | ||
|
|
aa137fb2d2 | ||
|
|
09284d512d | ||
|
|
02fd7e51ff | ||
|
|
b359b89aa1 | ||
|
|
873b20677e | ||
|
|
a049664219 | ||
|
|
64c6e25896 | ||
|
|
9f9122ab8e | ||
|
|
d0661cd4a3 | ||
|
|
707b19dc35 | ||
|
|
6fd15d66a7 | ||
|
|
8c9a814e18 | ||
|
|
74ef5f38e9 | ||
|
|
624a3ee1a7 | ||
|
|
fc658a25d7 | ||
|
|
308619a726 | ||
|
|
e87d8d9856 | ||
|
|
7594264725 | ||
|
|
69533ce8f5 | ||
|
|
9fac43a3a3 | ||
|
|
b00db39739 | ||
|
|
6f2a584279 | ||
|
|
de717268f7 | ||
|
|
e27b19c756 | ||
|
|
045cb461f1 | ||
|
|
088c0eedc6 | ||
|
|
e5137b03fc | ||
|
|
76d34a4d74 | ||
|
|
ae4f0e5728 | ||
|
|
5df59027ad | ||
|
|
c888e33f04 | ||
|
|
1a56ecaa39 | ||
|
|
d778c3cf19 | ||
|
|
8bf57c6226 | ||
|
|
3c762b8809 | ||
|
|
3561fd7c43 | ||
|
|
66bfc0ec64 | ||
|
|
7d0e576e3b | ||
|
|
aa330bc8c7 | ||
|
|
b4de492e0d | ||
|
|
5bf3114e6f | ||
|
|
d2b1a2e5a3 | ||
|
|
4b01f6359b | ||
|
|
bcfa62f45a | ||
|
|
e7e8a2ca5f | ||
|
|
5edeb0250b | ||
|
|
0c2657df78 | ||
|
|
e4c57e8031 | ||
|
|
6a25548097 | ||
|
|
db7cbdfc44 | ||
|
|
2f26badb84 | ||
|
|
f7e665c42f | ||
|
|
3bc44ee451 | ||
|
|
125de855ef | ||
|
|
3881ebcce0 | ||
|
|
bef5324fea | ||
|
|
c2655370e0 | ||
|
|
d017e34795 | ||
|
|
aa44da35ba | ||
|
|
5c4c6e68f6 | ||
|
|
a435363b94 | ||
|
|
d6634eb14e | ||
|
|
afee2cf71a | ||
|
|
79b0a6ba9c | ||
|
|
0c2438b36a | ||
|
|
d6da46f94b | ||
|
|
562e39c9c5 | ||
|
|
2d08e0955a | ||
|
|
baffa969d3 | ||
|
|
1fbc8739b9 | ||
|
|
b9dec84489 | ||
|
|
6feb864c38 | ||
|
|
b6db1898b1 | ||
|
|
de902d179e | ||
|
|
58b77e3427 | ||
|
|
cdcac86256 | ||
|
|
79b05e48e8 | ||
|
|
541146e8ce | ||
|
|
97b161c536 | ||
|
|
ba3a6ecb52 | ||
|
|
cf27b7440d | ||
|
|
407b9c9cd7 | ||
|
|
d0055310ba | ||
|
|
02f5fa32af | ||
|
|
b6590e95b5 | ||
|
|
ec65211d54 | ||
|
|
8dfa08f146 | ||
|
|
daef2d0546 | ||
|
|
15eaa80301 | ||
|
|
1e924a8530 | ||
|
|
23995ccb07 | ||
|
|
a4f2603454 | ||
|
|
cc860b4a76 | ||
|
|
0be82602ce | ||
|
|
b42c42692e | ||
|
|
7fcbff3ceb | ||
|
|
efec0af394 | ||
|
|
aafecd9d1e | ||
|
|
e37c43ea06 | ||
|
|
3fac7b5bb7 | ||
|
|
9b90114d03 | ||
|
|
7c5cfe6697 | ||
|
|
d1fd69337f | ||
|
|
3fc218111a | ||
|
|
c63fb0fc6b | ||
|
|
6fe4ac241d | ||
|
|
c385b80807 | ||
|
|
97f36fa46f | ||
|
|
856d4b39d1 | ||
|
|
01abd73a2a | ||
|
|
375c2a87c7 | ||
|
|
6ca507f8dd | ||
|
|
86b4a53858 | ||
|
|
8959ba9b82 | ||
|
|
a62a230d3d | ||
|
|
cc45129e9f | ||
|
|
bffc9d5aba | ||
|
|
f2b121cd58 | ||
|
|
fd30be7644 | ||
|
|
d9052c7e3c | ||
|
|
dcfe10b691 | ||
|
|
914a096b42 | ||
|
|
5fa9dcbc7e | ||
|
|
93ec01e0a1 | ||
|
|
bbc98db6b4 | ||
|
|
1f8d29a221 | ||
|
|
d267dd2515 | ||
|
|
51954c7f3d | ||
|
|
df842a8e8d | ||
|
|
60919488f1 | ||
|
|
4dbaaa63bb | ||
|
|
8cc4003837 | ||
|
|
35790c584b | ||
|
|
09d7cf2cc1 | ||
|
|
58d7c7f6ae | ||
|
|
cab24836d8 | ||
|
|
cf9ef615c9 | ||
|
|
8c96032b2b | ||
|
|
d256551907 | ||
|
|
e800e2db2b | ||
|
|
e5539c0d01 | ||
|
|
ea8621d6ec | ||
|
|
ac05a2ede7 | ||
|
|
808baf203d | ||
|
|
beeafc6bc5 | ||
|
|
6f8c977e73 | ||
|
|
9a2fbdde20 | ||
|
|
b325b2c003 | ||
|
|
feda23587c |
@@ -1,10 +1,65 @@
|
||||
# Hubzilla at Home next to your Router
|
||||
# How to use
|
||||
|
||||
This readme will show you how to install and run Hubzilla (or Zap) at home.
|
||||
## Disclaimers
|
||||
|
||||
The installation is done by a script.
|
||||
- This script does work with Debian 10 only.
|
||||
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation).
|
||||
|
||||
What the script will do for you...
|
||||
## Preconditions
|
||||
|
||||
Hardware
|
||||
|
||||
+ Internet connection and router at home
|
||||
+ Mini-pc connected to your router (a Raspberry 3 will do for very small Hubs)
|
||||
+ USB drive for backups
|
||||
|
||||
Software
|
||||
|
||||
+ Fresh installation of Debian 10 (Stretch)
|
||||
+ Router with open ports 80 and 443 for your web server
|
||||
|
||||
## How to run the script
|
||||
|
||||
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
|
||||
+ Log on to your fresh Debian
|
||||
- apt-get install git
|
||||
- mkdir -p /var/www
|
||||
- cd /var/www
|
||||
- git clone https://framagit.org/hubzilla/core.git html
|
||||
- cd html/.homeinstall
|
||||
- cp hubzilla-config.txt.template hubzilla-config.txt
|
||||
- nano hubzilla-config.txt
|
||||
- Read the comments carefully
|
||||
- Enter your values: db pass, domain, values for dyn DNS
|
||||
- Prepare your external disk for backups
|
||||
- hubzilla-setup.sh as root
|
||||
- ... wait, wait, wait until the script is finised
|
||||
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
|
||||
|
||||
## Optional - Set path to imagemagick
|
||||
|
||||
In Admin settings of hubzilla or via terminal
|
||||
|
||||
cd /var/www/html
|
||||
util/config system.imagick_convert_path /usr/bin/convert
|
||||
|
||||
## Optional - Switch verification of email on/off
|
||||
|
||||
Do this just befor you register the user.
|
||||
|
||||
In Admin settings of hubzilla or via terminal
|
||||
|
||||
cd /var/www/html
|
||||
|
||||
Check the current setting
|
||||
|
||||
util/config system verify_email
|
||||
|
||||
Switch the verification on/off (1/0)
|
||||
|
||||
util/config system verify_email 0
|
||||
|
||||
## What the script will do for you...
|
||||
|
||||
+ install everything required by Hubzilla, basically a web server (Apache), PHP, a database (MySQL), certbot,...
|
||||
+ create a database
|
||||
@@ -38,69 +93,11 @@ The script can install both [Hubzilla](https://zotlabs.org/page/hubzilla/hubzill
|
||||
- core: git clone https://framagit.org/zot/zap.git html (in this readme)
|
||||
- addons: util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons (in hubzilla-setup.sh)
|
||||
|
||||
## Disclaimers
|
||||
|
||||
- This script does work with Debian 10 only.
|
||||
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation).
|
||||
|
||||
# Step-by-Step Overwiew
|
||||
# Step-by-Step - some Details
|
||||
|
||||
## Preconditions
|
||||
|
||||
Hardware
|
||||
|
||||
+ Internet connection and router at home
|
||||
+ Mini-pc connected to your router (a Raspberry 3 will do for very small Hubs)
|
||||
+ USB drive for backups
|
||||
|
||||
Software
|
||||
|
||||
+ Fresh installation of Debian 10 (Stretch)
|
||||
+ Router with open ports 80 and 443 for your web server
|
||||
|
||||
## The basic steps (quick overview)
|
||||
|
||||
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
|
||||
+ Log on to your fresh Debian
|
||||
- apt-get install git
|
||||
- mkdir -p /var/www
|
||||
- cd /var/www
|
||||
- git clone https://framagit.org/hubzilla/core.git html
|
||||
- cd html/.homeinstall
|
||||
- cp hubzilla-config.txt.template hubzilla-config.txt
|
||||
- nano hubzilla-config.txt
|
||||
- Read the comments carefully
|
||||
- Enter your values: db pass, domain, values for dyn DNS
|
||||
- Prepare your external disk for backups
|
||||
- hubzilla-setup.sh as root
|
||||
- ... wait, wait, wait until the script is finised
|
||||
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If the check of the mail address fails when you try to register the very first user in the browser. Do...
|
||||
|
||||
cd /var/www/html
|
||||
util/config system.do_not_check_dns 1
|
||||
|
||||
## Optional - Set path to imagemagick
|
||||
|
||||
In Admin settings of hubzilla or via terminal
|
||||
|
||||
cd /var/www/html
|
||||
util/config system.imagick_convert_path /usr/bin/convert
|
||||
|
||||
# Step-by-Step in Detail
|
||||
|
||||
## Preparations Software
|
||||
|
||||
## Install Debian 9
|
||||
|
||||
Provided you use a Raspberry Pi 3...
|
||||
|
||||
Download the OS Raspbian from https://www.raspberrypi.org/downloads/raspbian/
|
||||
|
||||
Follow the installation instruction there.
|
||||
## Preparations
|
||||
|
||||
## Configure your Router
|
||||
|
||||
@@ -146,12 +143,5 @@ to boot the Rapsi to the client console.
|
||||
|
||||
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
|
||||
|
||||
On a Raspian Stretch (Debian 10) the validation of the mail address fails for the very first user.
|
||||
This used to happen on some *bsd distros but there was some work to fix that a year ago (2017).
|
||||
|
||||
So if your system isn't registered in DNS or DNS isn't active do
|
||||
|
||||
cd /var/www/html
|
||||
util/config system.do_not_check_dns 1
|
||||
|
||||
|
||||
|
||||
@@ -28,14 +28,13 @@
|
||||
# * php,
|
||||
# * mariadb - the database for hubzilla,
|
||||
# * adminer,
|
||||
# * git to download and update hubzilla addon
|
||||
# - download hubzilla core and addons
|
||||
# * git to download and update addons
|
||||
# - configure cron
|
||||
# * "Master.php" for regular background prozesses of hubzilla
|
||||
# * "apt-get update" and "apt-get dist-upgrade" and "apt-get autoremove" to keep linux up-to-date
|
||||
# * run command to keep the IP up-to-date > DynDNS provided by selfHOST.de or freedns.afraid.org
|
||||
# * backup hubzillas database and files (rsync)
|
||||
# - letsencrypt
|
||||
# - run letsencrypt to create, register and use a certifacte for https
|
||||
#
|
||||
#
|
||||
# Discussion
|
||||
@@ -56,7 +55,7 @@
|
||||
# - creates a daily cron that runs the hubzilla-daily.sh
|
||||
#
|
||||
# hubzilla-daily.sh makes a (daily) backup of all relevant files
|
||||
# - /var/lib/mysql/ > hubzilla database
|
||||
# - /var/lib/mysql/ > database
|
||||
# - /var/www/ > hubzilla/zap from github
|
||||
# - /etc/letsencrypt/ > certificates
|
||||
#
|
||||
@@ -223,6 +222,11 @@ function install_curl {
|
||||
nocheck_install "curl"
|
||||
}
|
||||
|
||||
function install_wget {
|
||||
print_info "installing wget..."
|
||||
nocheck_install "wget"
|
||||
}
|
||||
|
||||
function install_sendmail {
|
||||
print_info "installing sendmail..."
|
||||
nocheck_install "sendmail sendmail-bin"
|
||||
@@ -269,7 +273,19 @@ function install_adminer {
|
||||
else
|
||||
print_info "file /etc/adminer/adminer.conf exists already"
|
||||
fi
|
||||
|
||||
a2enmod rewrite
|
||||
|
||||
if [ ! -f /etc/apache2/apache2.conf ]
|
||||
then
|
||||
die "could not find file /etc/apache2/apache2.conf"
|
||||
fi
|
||||
sed -i \
|
||||
"s/AllowOverride None/AllowOverride all/" \
|
||||
/etc/apache2/apache2.conf
|
||||
|
||||
a2enconf adminer
|
||||
systemctl restart mariadb
|
||||
systemctl reload apache2
|
||||
}
|
||||
|
||||
@@ -407,10 +423,9 @@ function install_letsencrypt {
|
||||
then
|
||||
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
|
||||
fi
|
||||
# check if user gave mail address
|
||||
if [ -z "$le_email" ]
|
||||
then
|
||||
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
|
||||
die "Failed to install let's encrypt: 'le_email' is empty in $configfile"
|
||||
fi
|
||||
nocheck_install "certbot python-certbot-apache"
|
||||
print_info "run certbot ..."
|
||||
@@ -431,12 +446,19 @@ function check_https {
|
||||
}
|
||||
|
||||
function install_hubzilla {
|
||||
print_info "installing hubzilla addons..."
|
||||
print_info "installing addons..."
|
||||
cd /var/www/html/
|
||||
# if you install Hubzilla
|
||||
# util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
|
||||
# if you install ZAP
|
||||
util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons
|
||||
if git remote -v | grep -i "origin.*hubzilla.*core"
|
||||
then
|
||||
print_info "hubzilla"
|
||||
util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
|
||||
elif git remote -v | grep -i "origin.*zap.*core"
|
||||
then
|
||||
print_info "zap"
|
||||
util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons
|
||||
else
|
||||
die "neither zap nor hubzilla repository > did not install addons or zap/hubzilla"
|
||||
fi
|
||||
mkdir -p "store/[data]/smarty3"
|
||||
chmod -R 777 store
|
||||
touch .htconfig.php
|
||||
@@ -446,7 +468,7 @@ function install_hubzilla {
|
||||
chown root:www-data /var/www/html/
|
||||
chown root:www-data /var/www/html/.htaccess
|
||||
chmod 0644 /var/www/html/.htaccess
|
||||
print_info "installed hubzilla"
|
||||
print_info "installed addons"
|
||||
}
|
||||
|
||||
function install_rsync {
|
||||
@@ -585,6 +607,7 @@ check_config
|
||||
stop_hubzilla
|
||||
update_upgrade
|
||||
install_curl
|
||||
install_wget
|
||||
install_sendmail
|
||||
install_apache
|
||||
install_imagemagick
|
||||
@@ -600,23 +623,34 @@ configure_cron_selfhost
|
||||
|
||||
if [ "$le_domain" != "localhost" ]
|
||||
then
|
||||
install_letsencrypt
|
||||
check_https
|
||||
install_letsencrypt
|
||||
configure_apache_for_https
|
||||
check_https
|
||||
else
|
||||
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
|
||||
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
|
||||
fi
|
||||
|
||||
install_hubzilla
|
||||
|
||||
if [ "$le_domain" != "localhost" ]
|
||||
then
|
||||
rewrite_to_https
|
||||
install_rsnapshot
|
||||
else
|
||||
print_info "is localhost - skipped rewrite to https and installation of rsnapshot"
|
||||
fi
|
||||
|
||||
configure_cron_daily
|
||||
|
||||
if [ "$le_domain" != "localhost" ]
|
||||
then
|
||||
install_rsync
|
||||
install_cryptosetup
|
||||
install_cryptosetup
|
||||
write_uninstall_script
|
||||
else
|
||||
print_info "is localhost - skipped installation of cryptosetup"
|
||||
print_info "is localhost - skipped installation of cryptosetup"
|
||||
fi
|
||||
|
||||
|
||||
#set +x # stop debugging from here
|
||||
|
||||
|
||||
|
||||
74
CHANGELOG
@@ -1,3 +1,77 @@
|
||||
Hubzilla 4.6 (2019-12-04)
|
||||
- Improve opengraph support for channels
|
||||
- Add opengraph support for articles
|
||||
- Update abook_connected for RSS feeds only if handle_feed() returned success
|
||||
- Do not embed PDF files by default but allow to enabled this feature in security options
|
||||
- Check if file exists before we include it in the router
|
||||
- Update jquery to version 3.4.1
|
||||
- Update composer libraries
|
||||
- Remove old and unused javascript libraries
|
||||
- Improved BBcode to Markdown conversion
|
||||
- Introduce inline SVG support via BBcode
|
||||
- Sanitize title on Atom/RSS feed import
|
||||
- Improved HTTP headers cache support for photos
|
||||
- Add date headers to signed headers
|
||||
- Add check if item['tag'] is an array
|
||||
- Add hook comments_are_now_closed for addons to override date based comment closure
|
||||
- Change mysql schema for item.llink and item.plink for new installs from char(191) to text
|
||||
- Improved photo cache expiration
|
||||
- Improved plural function processing on translation strings creation from .po file with util/po2php utlility
|
||||
- Improved support for CDN/Infrastructure caching (especially profile images)
|
||||
- New japanese translation
|
||||
- Add connect button for non-zot networks not connected in current location
|
||||
- Allow to send forum channels wall2wall or sent by mentions post to external sites via addons
|
||||
- Allow addons to process forum posts published through mentions
|
||||
- Improved internal routing for ActivityPub messages
|
||||
- Improved admin documentation
|
||||
- Add ITEM_TYPE_CUSTOM and hooks to permit addons to create and distribute custom item types
|
||||
- Support "comment policy" in Zot6 communications
|
||||
- Add selected text as quote on reply if comment button is used
|
||||
- Add more nofollow tags to links to discourage backlink farmers
|
||||
- Improved conversion of emoji reactions from zot to zot6
|
||||
- Add CardDAV/CalDAV autodiscovery
|
||||
- Label source project of zotfeed since it is not completely compatible across projects
|
||||
- Update homeinstall script
|
||||
|
||||
Bugfixes
|
||||
- Fix once cached embedded content is used and stored forever
|
||||
- Fix wildcard tag issue
|
||||
- Fix duplicate attachment in jot fileupload
|
||||
- Fix regression with audio file upload
|
||||
- Fix can not edit menu name or title (#1402)
|
||||
- Fix pagination encoding issue for some server setups
|
||||
- Fix Zap->Hubzilla event title compatibility
|
||||
- Fix event timezones for Zot6
|
||||
- Fix missing summary in mod article_edit
|
||||
- Fix PHP warning failed to write session data using user defined save handler
|
||||
- Fix possible thumbnails distortion on rebuild with util/thumbrepair utility
|
||||
- Fix issues with image import to zot6
|
||||
- Fix attachment permissions on clonned channels sync
|
||||
- Fix entries without sitekey returned from DB in queue_deliver() and Lib/Queue
|
||||
|
||||
Addons
|
||||
- Twitter: send tweet even if attached image uploading was unsuccessful
|
||||
- Livejournal: add link to original post option
|
||||
- Flashcards: update to version 2.08
|
||||
- Pubcrawl: compatibility changes to support pixelfed
|
||||
- Cart: update paypal button to API v2
|
||||
- Photocache: rework for speed and lower memory consumption
|
||||
- Photocache: etag support for cached photos
|
||||
- Photocache: purge cache on addon uninstall
|
||||
- Openstreetmap: fix regression if no default values set
|
||||
- Livejournal: allow send posts from non channel owner
|
||||
- Pubcrawl: fix event timezones
|
||||
- Pubcrawl: better ActivityPub channel URL detection
|
||||
- Pubcrawl: fix comments delivery for other channels on the same hub
|
||||
- New addon "workflow" with initial basic "issue tracker" capability
|
||||
|
||||
|
||||
Hubzilla 4.4.1 (2019-08-16)
|
||||
- Fix wrong profile photo displayed when previewing and editing profiles
|
||||
- Fix regression from 4.4 which prevented encrypted signatures from being used for encrypted messages
|
||||
- Fix typo in queueworker addon which broke filtering of duplicate work
|
||||
|
||||
|
||||
Hubzilla 4.4 (2019-08-13)
|
||||
- Change primary directory from zotadel.net to hub.netzgemeinde.eu (requested by zotadel admin)
|
||||
- Add Russian context help files
|
||||
|
||||
@@ -40,6 +40,15 @@ class Cron {
|
||||
|
||||
require_once('include/sharedwithme.php');
|
||||
apply_updates();
|
||||
|
||||
/**
|
||||
* Chatpresence: if somebody hasn't pinged recently, they've most likely left the page
|
||||
* and shouldn't count as online anymore. We allow an expection for bots.
|
||||
*/
|
||||
q("delete from chatpresence where cp_last < %s - INTERVAL %s and cp_client != 'auto' ",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 MINUTE')
|
||||
);
|
||||
|
||||
// expire any expired mail
|
||||
|
||||
@@ -97,13 +106,17 @@ class Cron {
|
||||
|
||||
// Clean expired photos from cache
|
||||
|
||||
$age = get_config('system','active_expire_days', '30');
|
||||
$r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval($age . ' DAY')
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
|
||||
);
|
||||
if($r) {
|
||||
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
|
||||
);
|
||||
foreach($r as $rr) {
|
||||
$file = dbunescbin($rr['content']);
|
||||
if(is_file($file)) {
|
||||
@@ -113,11 +126,6 @@ class Cron {
|
||||
}
|
||||
}
|
||||
}
|
||||
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval($age . ' DAY')
|
||||
);
|
||||
|
||||
// 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
|
||||
@@ -215,7 +223,7 @@ class Cron {
|
||||
$restart = true;
|
||||
$generation = intval($argv[2]);
|
||||
if(! $generation)
|
||||
killme();
|
||||
return;
|
||||
}
|
||||
|
||||
reload_plugins();
|
||||
|
||||
@@ -44,6 +44,17 @@ class Cron_daily {
|
||||
db_utcnow(), db_quoteinterval('1 YEAR')
|
||||
);
|
||||
|
||||
// expire anonymous sse notification entries once a day
|
||||
|
||||
q("delete from xconfig where xchan like '%s'",
|
||||
dbesc('sse_id.%')
|
||||
);
|
||||
|
||||
// Clean up emdedded content cache
|
||||
q("DELETE FROM cache WHERE updated < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
|
||||
);
|
||||
|
||||
//update statistics in config
|
||||
require_once('include/statistics_fns.php');
|
||||
|
||||
@@ -13,7 +13,7 @@ class CurlAuth {
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
if($argc != 2)
|
||||
killme();
|
||||
return;
|
||||
|
||||
\App::$session->start();
|
||||
|
||||
@@ -50,6 +50,6 @@ class CurlAuth {
|
||||
|
||||
file_put_contents($c,$x);
|
||||
|
||||
killme();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ if(array_search( __file__ , get_included_files()) === 0) {
|
||||
|
||||
if($argc)
|
||||
Master::Release($argc,$argv);
|
||||
killme();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
require_once('include/queue_fn.php');
|
||||
require_once('include/html2plain.php');
|
||||
@@ -285,8 +286,21 @@ class Notifier {
|
||||
}
|
||||
|
||||
if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST ] )) {
|
||||
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
|
||||
return;
|
||||
$hookinfo=[
|
||||
'targetitem'=>$target_item,
|
||||
'deliver'=>false
|
||||
];
|
||||
if (intval($target_item['item_type'] == ITEM_TYPE_CUSTOM)) {
|
||||
call_hooks('customitem_deliver',$hookinfo);
|
||||
}
|
||||
|
||||
if (!$hookinfo['deliver']) {
|
||||
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$target_item = $hookinfo['targetitem'];
|
||||
|
||||
}
|
||||
|
||||
// Check for non published items, but allow an exclusion for transmitting hidden file activities
|
||||
@@ -353,9 +367,18 @@ class Notifier {
|
||||
$activity = json_decode($m,true);
|
||||
}
|
||||
else {
|
||||
$activity = \Zotlabs\Lib\Activity::encode_activity($target_item);
|
||||
$activity = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], Activity::encode_activity($target_item)
|
||||
);
|
||||
}
|
||||
|
||||
logger('target_item: ' . print_r($target_item,true), LOGGER_DEBUG);
|
||||
logger('encoded: ' . print_r($activity,true), LOGGER_DEBUG);
|
||||
|
||||
|
||||
// Send comments to the owner to re-deliver to everybody in the conversation
|
||||
// We only do this if the item in question originated on this site. This prevents looping.
|
||||
// To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
|
||||
|
||||
@@ -61,11 +61,13 @@ class Onepoll {
|
||||
|
||||
if($contact['xchan_network'] === 'rss') {
|
||||
logger('onepoll: processing feed ' . $contact['xchan_name'], LOGGER_DEBUG);
|
||||
handle_feed($importer['channel_id'],$contact_id,$contact['xchan_hash']);
|
||||
q("update abook set abook_connected = '%s' where abook_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
$alive = handle_feed($importer['channel_id'],$contact_id,$contact['xchan_hash']);
|
||||
if ($alive) {
|
||||
q("update abook set abook_connected = '%s' where abook_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ class Poller {
|
||||
$restart = true;
|
||||
$generation = intval($argv[2]);
|
||||
if(! $generation)
|
||||
killme();
|
||||
return;
|
||||
}
|
||||
|
||||
if(($argc > 1) && intval($argv[1])) {
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
require_once('include/event.php');
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
class Activity {
|
||||
|
||||
@@ -40,6 +42,8 @@ class Activity {
|
||||
if($x['type'] === ACTIVITY_OBJ_PHOTO) {
|
||||
return self::fetch_image($x);
|
||||
}
|
||||
|
||||
call_hooks('encode_object',$x);
|
||||
}
|
||||
|
||||
return $x;
|
||||
@@ -63,12 +67,32 @@ class Activity {
|
||||
}
|
||||
else {
|
||||
$m = parse_url($url);
|
||||
|
||||
// handle bearcaps
|
||||
if ($m['scheme'] === 'bear') {
|
||||
$params = explode('&',$m['query']);
|
||||
if ($params) {
|
||||
foreach ($params as $p) {
|
||||
if (substr($p,0,2) === 'u=') {
|
||||
$url = substr($p,2);
|
||||
}
|
||||
if (substr($p,0,2) === 't=') {
|
||||
$token = substr($p,2);
|
||||
}
|
||||
}
|
||||
$m = parse_url($url);
|
||||
}
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'Accept' => 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'get ' . get_request_string($url),
|
||||
'Date' => datetime_convert('UTC','UTC','now','D, d M Y H:i:s') . ' UTC'
|
||||
'Date' => datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T'),
|
||||
'(request-target)' => 'get ' . get_request_string($url)
|
||||
];
|
||||
if (isset($token)) {
|
||||
$headers['Authorization'] = 'Bearer ' . $token;
|
||||
}
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
|
||||
$x = z_fetch_url($url, true, $redirects, [ 'headers' => $h ] );
|
||||
}
|
||||
@@ -144,6 +168,10 @@ class Activity {
|
||||
if($r) {
|
||||
xchan_query($r,true);
|
||||
$r = fetch_post_tags($r,true);
|
||||
if ($r[0]['verb'] === 'Create' && $r[0]['obj_type'] === ACTIVITY_OBJ_EVENT) {
|
||||
$r[0]['verb'] = 'Invite';
|
||||
return self::encode_activity($r[0]);
|
||||
}
|
||||
return self::encode_item($r[0]);
|
||||
}
|
||||
}
|
||||
@@ -178,6 +206,11 @@ class Activity {
|
||||
$ev = bbtoevent($x['content']);
|
||||
if($ev) {
|
||||
|
||||
|
||||
if (! $ev['timezone']) {
|
||||
$ev['timezone'] = 'UTC';
|
||||
}
|
||||
|
||||
$actor = null;
|
||||
if(array_key_exists('author',$x) && array_key_exists('link',$x['author'])) {
|
||||
$actor = $x['author']['link'][0]['href'];
|
||||
@@ -185,16 +218,17 @@ class Activity {
|
||||
$y = [
|
||||
'type' => 'Event',
|
||||
'id' => z_root() . '/event/' . $ev['event_hash'],
|
||||
'summary' => bbcode($ev['summary'], [ 'cache' => true ]),
|
||||
'name' => $ev['summary'],
|
||||
// 'summary' => bbcode($ev['summary'], [ 'cache' => true ]),
|
||||
// RFC3339 Section 4.3
|
||||
'startTime' => (($ev['adjust']) ? datetime_convert('UTC','UTC',$ev['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$ev['dtstart'],'Y-m-d\\TH:i:s-00:00')),
|
||||
'startTime' => (($ev['adjust']) ? datetime_convert($ev['timezone'],'UTC',$ev['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$ev['dtstart'],'Y-m-d\\TH:i:s-00:00')),
|
||||
'content' => bbcode($ev['description'], [ 'cache' => true ]),
|
||||
'location' => [ 'type' => 'Place', 'content' => bbcode($ev['location'], [ 'cache' => true ]) ],
|
||||
'source' => [ 'content' => format_event_bbcode($ev), 'mediaType' => 'text/bbcode' ],
|
||||
'source' => [ 'content' => format_event_bbcode($ev,true), 'mediaType' => 'text/bbcode' ],
|
||||
'actor' => $actor,
|
||||
];
|
||||
if(! $ev['nofinish']) {
|
||||
$y['endTime'] = (($ev['adjust']) ? datetime_convert('UTC','UTC',$ev['dtend'], ATOM_TIME) : datetime_convert('UTC','UTC',$ev['dtend'],'Y-m-d\\TH:i:s-00:00'));
|
||||
$y['endTime'] = (($ev['adjust']) ? datetime_convert($ev['timezone'],'UTC',$ev['dtend'], ATOM_TIME) : datetime_convert('UTC','UTC',$ev['dtend'],'Y-m-d\\TH:i:s-00:00'));
|
||||
}
|
||||
|
||||
// copy attachments from the passed object - these are already formatted for ActivityStreams
|
||||
@@ -274,8 +308,14 @@ class Activity {
|
||||
|
||||
$ret = [];
|
||||
|
||||
$objtype = self::activity_obj_mapper($i['obj_type']);
|
||||
|
||||
if($i['verb'] === ACTIVITY_FRIEND) {
|
||||
// Hubzilla 'make-friend' activity, no direct mapping from AS1 to AS2 - make it a note
|
||||
$objtype = 'Note';
|
||||
}
|
||||
else {
|
||||
$objtype = self::activity_obj_mapper($i['obj_type']);
|
||||
}
|
||||
|
||||
if(intval($i['item_deleted'])) {
|
||||
$ret['type'] = 'Tombstone';
|
||||
$ret['formerType'] = $objtype;
|
||||
@@ -285,6 +325,22 @@ class Activity {
|
||||
|
||||
$ret['type'] = $objtype;
|
||||
|
||||
if ($objtype === 'Question') {
|
||||
if ($i['obj']) {
|
||||
if (is_array($i['obj'])) {
|
||||
$ret = $i['obj'];
|
||||
}
|
||||
else {
|
||||
$ret = json_decode($i['obj'],true);
|
||||
}
|
||||
|
||||
if(array_path_exists('actor/id',$ret)) {
|
||||
$ret['actor'] = $ret['actor']['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/item/' . urlencode($i['mid']));
|
||||
|
||||
if($i['title'])
|
||||
@@ -312,10 +368,21 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if (intval($i['item_wall']) && $i['mid'] === $i['parent_mid']) {
|
||||
$ret['commentPolicy'] = map_scope(PermissionLimits::Get($i['uid'],'post_comments'));
|
||||
}
|
||||
|
||||
if (intval($i['item_private']) === 2) {
|
||||
$ret['directMessage'] = true;
|
||||
}
|
||||
|
||||
if (array_key_exists('comments_closed',$i) && $i['comments_closed'] !== EMPTY_STR && $i['comments_closed'] !== NULL_DATE) {
|
||||
if($ret['commentPolicy']) {
|
||||
$ret['commentPolicy'] .= ' ';
|
||||
}
|
||||
$ret['commentPolicy'] .= 'until=' . datetime_convert('UTC','UTC',$i['comments_closed'],ATOM_TIME);
|
||||
}
|
||||
|
||||
$ret['attributedTo'] = $i['author']['xchan_url'];
|
||||
|
||||
if($i['id'] != $i['parent']) {
|
||||
@@ -354,26 +421,30 @@ class Activity {
|
||||
|
||||
$ret = [];
|
||||
|
||||
if($item['tag']) {
|
||||
foreach($item['tag'] as $t) {
|
||||
if(! array_key_exists('type',$t))
|
||||
if ($item['tag'] && is_array($item['tag'])) {
|
||||
$ptr = $item['tag'];
|
||||
if (! array_key_exists(0,$ptr)) {
|
||||
$ptr = [ $ptr ];
|
||||
}
|
||||
foreach ($ptr as $t) {
|
||||
if (! array_key_exists('type',$t))
|
||||
$t['type'] = 'Hashtag';
|
||||
|
||||
switch($t['type']) {
|
||||
case 'Hashtag':
|
||||
$ret[] = [ 'ttype' => TERM_HASHTAG, 'url' => ((isset($t['href'])) ? $t['href'] : $t['id']), 'term' => escape_tags((substr($t['name'],0,1) === '#') ? substr($t['name'],1) : $t['name']) ];
|
||||
$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 === '!') {
|
||||
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;
|
||||
}
|
||||
@@ -384,6 +455,7 @@ class Activity {
|
||||
}
|
||||
|
||||
|
||||
|
||||
static function encode_taxonomy($item) {
|
||||
|
||||
$ret = [];
|
||||
@@ -467,6 +539,12 @@ 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'] = [];
|
||||
}
|
||||
|
||||
if(intval($i['item_deleted'])) {
|
||||
$ret['type'] = 'Tombstone';
|
||||
$ret['formerType'] = self::activity_obj_mapper($i['obj_type']);
|
||||
@@ -479,11 +557,6 @@ class Activity {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if($i['verb'] === ACTIVITY_FRIEND) {
|
||||
// Hubzilla 'make-friend' activity, no direct mapping from AS1 to AS2 - make it a note
|
||||
$ret['obj_type'] = ACTIVITY_OBJ_NOTE;
|
||||
$ret['obj'] = [];
|
||||
}
|
||||
|
||||
$ret['type'] = self::activity_mapper($i['verb']);
|
||||
|
||||
@@ -497,11 +570,37 @@ class Activity {
|
||||
xchan_query($p,true);
|
||||
$p = fetch_post_tags($p,true);
|
||||
$i['obj'] = self::encode_item($p[0]);
|
||||
|
||||
// convert to zot6 emoji reaction encoding which uses the target object to indicate the
|
||||
// specific emoji instead of overloading the verb or type.
|
||||
|
||||
$im = explode('#',$i['verb']);
|
||||
if($im && count($im) > 1)
|
||||
$emoji = $im[1];
|
||||
if(preg_match("/\[img(.*?)\](.*?)\[\/img\]/ism", $i['body'], $match)) {
|
||||
$ln = $match[2];
|
||||
}
|
||||
|
||||
$i['tgt_type'] = 'Image';
|
||||
|
||||
$i['target'] = [
|
||||
'type' => 'Image',
|
||||
'name' => $emoji,
|
||||
'url' => (($ln) ? $ln : z_root() . '/images/emoji/' . $emoji . '.png')
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/activity/' . urlencode($i['mid']));
|
||||
if (strpos($i['mid'],z_root() . '/item/') !== false) {
|
||||
$ret['id'] = str_replace('/item/','/activity/',$i['mid']);
|
||||
}
|
||||
elseif (strpos($i['mid'],z_root() . '/event/') !== false) {
|
||||
$ret['id'] = str_replace('/event/','/activity/',$i['mid']);
|
||||
}
|
||||
else {
|
||||
$ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/activity/' . urlencode($i['mid']));
|
||||
}
|
||||
|
||||
if($i['title'])
|
||||
$ret['name'] = html2plain(bbcode($i['title'], [ 'cache' => true ]));
|
||||
@@ -537,9 +636,15 @@ class Activity {
|
||||
}
|
||||
|
||||
if($i['id'] != $i['parent']) {
|
||||
$ret['inReplyTo'] = ((strpos($i['thr_parent'],'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
|
||||
$reply = true;
|
||||
|
||||
// inReplyTo needs to be set in the activity for followup actions (Like, Dislike, Announce, etc.),
|
||||
// but *not* for comments and RSVPs, where it should only be present in the object
|
||||
|
||||
if (! in_array($ret['type'],[ 'Create','Update','Accept','Reject','TentativeAccept','TentativeReject' ])) {
|
||||
$ret['inReplyTo'] = ((strpos($i['thr_parent'],'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
|
||||
}
|
||||
|
||||
if($i['item_private']) {
|
||||
$d = q("select xchan_url, xchan_addr, xchan_name from item left join xchan on xchan_hash = author_xchan where id = %d limit 1",
|
||||
intval($i['parent'])
|
||||
@@ -577,7 +682,7 @@ class Activity {
|
||||
$i['obj'] = json_decode($i['obj'],true);
|
||||
}
|
||||
if($i['obj']['type'] === ACTIVITY_OBJ_PHOTO) {
|
||||
$i['obj']['id'] = $i['id'];
|
||||
$i['obj']['id'] = $i['mid'];
|
||||
}
|
||||
|
||||
$obj = self::encode_object($i['obj']);
|
||||
@@ -594,6 +699,9 @@ class Activity {
|
||||
return [];
|
||||
}
|
||||
|
||||
if(array_path_exists('object/type',$ret) && $ret['object']['type'] === 'Event' && $ret['type'] === 'Create') {
|
||||
$ret['type'] = 'Invite';
|
||||
}
|
||||
|
||||
if($i['target']) {
|
||||
if(! is_array($i['target'])) {
|
||||
@@ -668,8 +776,24 @@ class Activity {
|
||||
}
|
||||
$ret = [];
|
||||
|
||||
$c = ((array_key_exists('channel_id',$p)) ? $p : channelx_by_hash($p['xchan_hash']));
|
||||
|
||||
$ret['type'] = 'Person';
|
||||
$ret['id'] = $p['xchan_url'];
|
||||
|
||||
if ($c) {
|
||||
$role = get_pconfig($c['channel_id'],'system','permissions_role');
|
||||
if (strpos($role,'forum') !== false) {
|
||||
$ret['type'] = 'Group';
|
||||
}
|
||||
}
|
||||
|
||||
if ($c) {
|
||||
$ret['id'] = channel_url($c);
|
||||
}
|
||||
else {
|
||||
$ret['id'] = ((strpos($p['xchan_hash'],'http') === 0) ? $p['xchan_hash'] : $p['xchan_url']);
|
||||
}
|
||||
|
||||
if($p['xchan_addr'] && strpos($p['xchan_addr'],'@'))
|
||||
$ret['preferredUsername'] = substr($p['xchan_addr'],0,strpos($p['xchan_addr'],'@'));
|
||||
$ret['name'] = $p['xchan_name'];
|
||||
@@ -728,9 +852,11 @@ class Activity {
|
||||
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
|
||||
'http://purl.org/zot/activity/attendyes' => 'Accept',
|
||||
'http://purl.org/zot/activity/attendno' => 'Reject',
|
||||
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept'
|
||||
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
|
||||
'Invite' => 'Invite',
|
||||
];
|
||||
|
||||
call_hooks('activity_mapper',$acts);
|
||||
|
||||
if(array_key_exists($verb,$acts) && $acts[$verb]) {
|
||||
return $acts[$verb];
|
||||
@@ -743,6 +869,9 @@ class Activity {
|
||||
if(strpos($verb,ACTIVITY_MOOD) !== false)
|
||||
return 'Create';
|
||||
|
||||
if(strpos($verb,ACTIVITY_FRIEND) !== false)
|
||||
return 'Create';
|
||||
|
||||
if(strpos($verb,ACTIVITY_POKE) !== false)
|
||||
return 'Activity';
|
||||
|
||||
@@ -770,9 +899,11 @@ class Activity {
|
||||
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
|
||||
'http://purl.org/zot/activity/attendyes' => 'Accept',
|
||||
'http://purl.org/zot/activity/attendno' => 'Reject',
|
||||
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept'
|
||||
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
|
||||
'Invite' => 'Invite',
|
||||
];
|
||||
|
||||
call_hooks('activity_decode_mapper',$acts);
|
||||
|
||||
foreach($acts as $k => $v) {
|
||||
if($verb === $v) {
|
||||
@@ -803,9 +934,12 @@ class Activity {
|
||||
'http://purl.org/zot/activity/thing' => 'Object',
|
||||
'http://purl.org/zot/activity/file' => 'zot:File',
|
||||
'http://purl.org/zot/activity/mood' => 'zot:Mood',
|
||||
|
||||
'Invite' => 'Invite',
|
||||
'Question' => 'Question'
|
||||
];
|
||||
|
||||
call_hooks('activity_obj_decode_mapper',$objs);
|
||||
|
||||
foreach($objs as $k => $v) {
|
||||
if($obj === $v) {
|
||||
return $k;
|
||||
@@ -821,10 +955,6 @@ class Activity {
|
||||
|
||||
static function activity_obj_mapper($obj) {
|
||||
|
||||
if(strpos($obj,'/') === false) {
|
||||
return $obj;
|
||||
}
|
||||
|
||||
$objs = [
|
||||
'http://activitystrea.ms/schema/1.0/note' => 'Note',
|
||||
'http://activitystrea.ms/schema/1.0/comment' => 'Note',
|
||||
@@ -840,9 +970,21 @@ class Activity {
|
||||
'http://purl.org/zot/activity/thing' => 'Object',
|
||||
'http://purl.org/zot/activity/file' => 'zot:File',
|
||||
'http://purl.org/zot/activity/mood' => 'zot:Mood',
|
||||
|
||||
'Invite' => 'Invite',
|
||||
'Question' => 'Question'
|
||||
];
|
||||
|
||||
call_hooks('activity_obj_mapper',$objs);
|
||||
|
||||
if ($obj === 'Answer') {
|
||||
return 'Note';
|
||||
}
|
||||
|
||||
if (strpos($obj,'/') === false) {
|
||||
return $obj;
|
||||
}
|
||||
|
||||
|
||||
if(array_key_exists($obj,$objs)) {
|
||||
return $objs[$obj];
|
||||
}
|
||||
@@ -1493,6 +1635,73 @@ class Activity {
|
||||
}
|
||||
|
||||
|
||||
|
||||
static function update_poll($item,$mid,$content) {
|
||||
$multi = false;
|
||||
if (! $item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$o = json_decode($item['obj'],true);
|
||||
if ($o && array_key_exists('anyOf',$o)) {
|
||||
$multi = true;
|
||||
}
|
||||
$answer_found = false;
|
||||
$found = false;
|
||||
if ($multi) {
|
||||
for ($c = 0; $c < count($o['anyOf']); $c ++) {
|
||||
if ($o['anyOf'][$c]['name'] === $content) {
|
||||
$answer_found = true;
|
||||
if (is_array($o['anyOf'][$c]['replies'])) {
|
||||
foreach($o['anyOf'][$c]['replies'] as $reply) {
|
||||
if(is_array($reply) && array_key_exists('id',$reply) && $reply['id'] === $mid) {
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! $found) {
|
||||
$o['anyOf'][$c]['replies']['totalItems'] ++;
|
||||
$o['anyOf'][$c]['replies']['items'][] = [ 'id' => $mid, 'type' => 'Note' ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for ($c = 0; $c < count($o['oneOf']); $c ++) {
|
||||
if ($o['oneOf'][$c]['name'] === $content) {
|
||||
$answer_found = true;
|
||||
if (is_array($o['oneOf'][$c]['replies'])) {
|
||||
foreach($o['oneOf'][$c]['replies'] as $reply) {
|
||||
if(is_array($reply) && array_key_exists('id',$reply) && $reply['id'] === $mid) {
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! $found) {
|
||||
$o['oneOf'][$c]['replies']['totalItems'] ++;
|
||||
$o['oneOf'][$c]['replies']['items'][] = [ 'id' => $mid, 'type' => 'Note' ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
logger('updated_poll: ' . print_r($o,true),LOGGER_DATA);
|
||||
if ($answer_found && ! $found) {
|
||||
$x = q("update item set obj = '%s', edited = '%s' where id = %d",
|
||||
dbesc(json_encode($o)),
|
||||
dbesc(datetime_convert()),
|
||||
intval($item['id'])
|
||||
);
|
||||
Master::Summon( [ 'Notifier', 'wall-new', $item['id'] ] );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static function decode_note($act) {
|
||||
|
||||
$response_activity = false;
|
||||
@@ -1531,7 +1740,6 @@ class Activity {
|
||||
$s['expires'] = datetime_convert('UTC','UTC',$act->obj['expires']);
|
||||
}
|
||||
|
||||
|
||||
if(in_array($act->type, [ 'Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'emojiReaction' ])) {
|
||||
|
||||
$response_activity = true;
|
||||
@@ -1561,15 +1769,23 @@ class Activity {
|
||||
if($act->type === 'Dislike') {
|
||||
$content['content'] = sprintf( t('Doesn\'t like %1$s\'s %2$s'),$mention,$act->obj['type']) . "\n\n" . $content['content'];
|
||||
}
|
||||
if($act->type === 'Accept' && $act->obj['type'] === 'Event' ) {
|
||||
$content['content'] = sprintf( t('Will attend %1$s\'s %2$s'),$mention,$act->obj['type']) . "\n\n" . $content['content'];
|
||||
}
|
||||
if($act->type === 'Reject' && $act->obj['type'] === 'Event' ) {
|
||||
$content['content'] = sprintf( t('Will not attend %1$s\'s %2$s'),$mention,$act->obj['type']) . "\n\n" . $content['content'];
|
||||
}
|
||||
if($act->type === 'TentativeAccept' && $act->obj['type'] === 'Event' ) {
|
||||
$content['content'] = sprintf( t('May attend %1$s\'s %2$s'),$mention,$act->obj['type']) . "\n\n" . $content['content'];
|
||||
|
||||
// handle event RSVPs
|
||||
if (($act->obj['type'] === 'Event') || ($act->obj['type'] === 'Invite' && array_path_exists('object/type',$act->obj) && $act->obj['object']['type'] === 'Event')) {
|
||||
if ($act->type === 'Accept') {
|
||||
$content['content'] = sprintf( t('Will attend %s\'s event'),$mention) . EOL . EOL . $content['content'];
|
||||
}
|
||||
if ($act->type === 'Reject') {
|
||||
$content['content'] = sprintf( t('Will not attend %s\'s event'),$mention) . EOL . EOL . $content['content'];
|
||||
}
|
||||
if ($act->type === 'TentativeAccept') {
|
||||
$content['content'] = sprintf( t('May attend %s\'s event'),$mention) . EOL . EOL . $content['content'];
|
||||
}
|
||||
if ($act->type === 'TentativeReject') {
|
||||
$content['content'] = sprintf( t('May not attend %s\'s event'),$mention) . EOL . EOL . $content['content'];
|
||||
}
|
||||
}
|
||||
|
||||
if($act->type === 'Announce') {
|
||||
$content['content'] = sprintf( t('🔁 Repeated %1$s\'s %2$s'), $mention, $act->obj['type']);
|
||||
}
|
||||
@@ -1590,37 +1806,58 @@ class Activity {
|
||||
|
||||
$s['verb'] = self::activity_decode_mapper($act->type);
|
||||
|
||||
// Mastodon does not provide update timestamps when updating poll tallies which means race conditions may occur here.
|
||||
if ($act->type === 'Update' && $act->obj['type'] === 'Question' && $s['edited'] === $s['created']) {
|
||||
$s['edited'] = datetime_convert();
|
||||
}
|
||||
|
||||
if($act->type === 'Tombstone' || $act->type === 'Delete' || ($act->type === 'Create' && $act->obj['type'] === 'Tombstone')) {
|
||||
$s['item_deleted'] = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$s['obj_type'] = self::activity_obj_decode_mapper($act->obj['type']);
|
||||
if($s['obj_type'] === ACTIVITY_OBJ_NOTE && $s['mid'] !== $s['parent_mid']) {
|
||||
$s['obj_type'] = ACTIVITY_OBJ_COMMENT;
|
||||
}
|
||||
|
||||
$eventptr = null;
|
||||
|
||||
if ($act->obj['type'] === 'Invite' && array_path_exists('object/type',$act->obj) && $act->obj['object']['type'] === 'Event') {
|
||||
$eventptr = $act->obj['object'];
|
||||
$s['mid'] = $s['parent_mid'] = $act->obj['id'];
|
||||
}
|
||||
|
||||
if($act->obj['type'] === 'Event') {
|
||||
if ($act->type === 'Invite') {
|
||||
$s['mid'] = $s['parent_mid'] = $act->id;
|
||||
}
|
||||
$eventptr = $act->obj;
|
||||
}
|
||||
|
||||
if ($eventptr) {
|
||||
|
||||
$s['obj'] = [];
|
||||
$s['obj']['asld'] = $act->obj;
|
||||
$s['obj']['asld'] = $eventptr;
|
||||
$s['obj']['type'] = ACTIVITY_OBJ_EVENT;
|
||||
$s['obj']['id'] = $act->obj['id'];
|
||||
$s['obj']['title'] = $act->obj['summary'];
|
||||
$s['obj']['id'] = $eventptr['id'];
|
||||
$s['obj']['title'] = $eventptr['name'];
|
||||
|
||||
if(strpos($act->obj['startTime'],'Z'))
|
||||
$s['obj']['adjust'] = true;
|
||||
else
|
||||
$s['obj']['adjust'] = false;
|
||||
|
||||
$s['obj']['dtstart'] = datetime_convert('UTC','UTC',$act->obj['startTime']);
|
||||
$s['obj']['dtstart'] = datetime_convert('UTC','UTC',$eventptr['startTime']);
|
||||
if($act->obj['endTime'])
|
||||
$s['obj']['dtend'] = datetime_convert('UTC','UTC',$act->obj['endTime']);
|
||||
$s['obj']['dtend'] = datetime_convert('UTC','UTC',$eventptr['endTime']);
|
||||
else
|
||||
$s['obj']['nofinish'] = true;
|
||||
$s['obj']['description'] = $act->obj['content'];
|
||||
$s['obj']['description'] = $eventptr['content'];
|
||||
|
||||
if(array_path_exists('location/content',$act->obj))
|
||||
$s['obj']['location'] = $act->obj['location']['content'];
|
||||
if(array_path_exists('location/content',$eventptr))
|
||||
$s['obj']['location'] = $eventptr['location']['content'];
|
||||
|
||||
}
|
||||
else {
|
||||
@@ -1662,6 +1899,18 @@ class Activity {
|
||||
}
|
||||
|
||||
|
||||
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['closed']) {
|
||||
$s['comments_closed'] = datetime_convert('UTC','UTC', $act->obj['closed']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// we will need a hook here to extract magnet links e.g. peertube
|
||||
// right now just link to the largest mp4 we find that will fit in our
|
||||
// standard content region
|
||||
@@ -1853,9 +2102,15 @@ class Activity {
|
||||
$s['plink'] = $s['mid'];
|
||||
}
|
||||
|
||||
if($act->recips && (! in_array(ACTIVITY_PUBLIC_INBOX,$act->recips)))
|
||||
if ($act->recips && (! in_array(ACTIVITY_PUBLIC_INBOX,$act->recips)))
|
||||
$s['item_private'] = 1;
|
||||
|
||||
if (is_array($act->obj)) {
|
||||
if (array_key_exists('directMessage',$act->obj) && intval($act->obj['directMessage'])) {
|
||||
$s['item_private'] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
set_iconfig($s,'activitypub','recips',$act->raw_recips);
|
||||
|
||||
$parent = (($s['parent_mid'] && $s['parent_mid'] === $s['mid']) ? true : false);
|
||||
@@ -1863,6 +2118,15 @@ class Activity {
|
||||
set_iconfig($s,'activitypub','rawmsg',$act->raw,1);
|
||||
}
|
||||
|
||||
$hookinfo = [
|
||||
'act' => $act,
|
||||
's' => $s
|
||||
];
|
||||
|
||||
call_hooks('decode_note',$hookinfo);
|
||||
|
||||
$s = $hookinfo['s'];
|
||||
|
||||
return $s;
|
||||
|
||||
}
|
||||
@@ -1935,7 +2199,7 @@ class Activity {
|
||||
set_iconfig($item,'activitypub','recips',$act->raw_recips);
|
||||
|
||||
if(! $is_parent) {
|
||||
$p = q("select parent_mid from item where mid = '%s' and uid = %d limit 1",
|
||||
$p = q("select parent_mid, id, obj_type from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($item['parent_mid']),
|
||||
intval($item['uid'])
|
||||
);
|
||||
@@ -1965,6 +2229,15 @@ class Activity {
|
||||
// $s['thr_parent'] = $s['mid'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($p[0]['obj_type'] === 'Question') {
|
||||
if ($item['obj_type'] === ACTIVITY_OBJ_NOTE && $item['title'] && (! $item['content'])) {
|
||||
$item['obj_type'] = 'Answer';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($p[0]['parent_mid'] !== $item['parent_mid']) {
|
||||
$item['thr_parent'] = $item['parent_mid'];
|
||||
}
|
||||
@@ -2052,16 +2325,25 @@ class Activity {
|
||||
break;
|
||||
|
||||
}
|
||||
if(! $item) {
|
||||
break;
|
||||
|
||||
$hookinfo = [
|
||||
'a' => $a,
|
||||
'item' => $item
|
||||
];
|
||||
|
||||
call_hooks('fetch_and_store',$hookinfo);
|
||||
|
||||
$item = $hookinfo['item'];
|
||||
|
||||
if($item) {
|
||||
|
||||
array_unshift($p,[ $a, $item, $replies]);
|
||||
|
||||
if($item['parent_mid'] === $item['mid'] || count($p) > 20) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
array_unshift($p,[ $a, $item, $replies]);
|
||||
|
||||
if($item['parent_mid'] === $item['mid'] || count($p) > 20) {
|
||||
break;
|
||||
}
|
||||
|
||||
$current_act = $a;
|
||||
$current_item = $item;
|
||||
}
|
||||
@@ -2110,11 +2392,19 @@ class Activity {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(! $item) {
|
||||
break;
|
||||
}
|
||||
|
||||
array_unshift($p,[ $a, $item ]);
|
||||
$hookinfo = [
|
||||
'a' => $a,
|
||||
'item' => $item
|
||||
];
|
||||
|
||||
call_hooks('fetch_and_store',$hookinfo);
|
||||
|
||||
$item = $hookinfo['item'];
|
||||
|
||||
if($item) {
|
||||
array_unshift($p,[ $a, $item ]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2495,7 +2785,12 @@ class Activity {
|
||||
}
|
||||
|
||||
if($event) {
|
||||
$event['summary'] = html2bbcode($content['summary']);
|
||||
$event['summary'] = $content['name'];
|
||||
if(! $event['summary']) {
|
||||
if($content['summary']) {
|
||||
$event['summary'] = html2plain($content['summary']);
|
||||
}
|
||||
}
|
||||
$event['description'] = html2bbcode($content['content']);
|
||||
if($event['summary'] && $event['dtstart']) {
|
||||
$content['event'] = $event;
|
||||
|
||||
@@ -101,7 +101,13 @@ class ActivityStreams {
|
||||
$this->actor = $this->get_actor('attributedTo',$this->obj);
|
||||
}
|
||||
}
|
||||
|
||||
// fetch recursive or embedded activities
|
||||
|
||||
if ($this->obj && is_array($this->obj) && array_key_exists('object',$this->obj)) {
|
||||
$this->obj['object'] = $this->get_compound_property($this->obj['object']);
|
||||
}
|
||||
|
||||
if($this->obj && is_array($this->obj) && $this->obj['actor'])
|
||||
$this->obj['actor'] = $this->get_actor('actor',$this->obj);
|
||||
if($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
|
||||
|
||||
@@ -74,7 +74,6 @@ class Apps {
|
||||
'Directory',
|
||||
'Search',
|
||||
'Help',
|
||||
'Mail',
|
||||
'Profile Photo'
|
||||
]);
|
||||
|
||||
|
||||
@@ -7,12 +7,23 @@ namespace Zotlabs\Lib;
|
||||
*/
|
||||
|
||||
class Cache {
|
||||
public static function get($key) {
|
||||
|
||||
/**
|
||||
* @brief Returns cached content
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $age in SQL format, default is '30 DAY'
|
||||
* @return string
|
||||
*/
|
||||
|
||||
public static function get($key, $age = '') {
|
||||
|
||||
$hash = hash('whirlpool',$key);
|
||||
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($hash)
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' AND updated > %s - INTERVAL %s LIMIT 1",
|
||||
dbesc($hash),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(($age ? $age : get_config('system','object_cache_days', '30') . ' DAY'))
|
||||
);
|
||||
|
||||
if ($r)
|
||||
@@ -40,12 +51,4 @@ class Cache {
|
||||
dbesc(datetime_convert()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function clear() {
|
||||
q("DELETE FROM cache WHERE updated < '%s'",
|
||||
dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -550,6 +550,11 @@ class Enotify {
|
||||
if ((\App::$language === 'en' || (! \App::$language)) && strpos($msg,', '))
|
||||
$msg = substr($msg,strpos($msg,', ')+1);
|
||||
|
||||
$datarray['id'] = $notify_id;
|
||||
$datarray['msg'] = $msg;
|
||||
|
||||
call_hooks('enotify_store_end', $datarray);
|
||||
|
||||
$r = q("update notify set msg = '%s' where id = %d and uid = %d",
|
||||
dbesc($msg),
|
||||
intval($notify_id),
|
||||
@@ -805,11 +810,12 @@ class Enotify {
|
||||
}
|
||||
else {
|
||||
$itemem_text = (($item['item_thread_top'])
|
||||
? t('created a new post')
|
||||
: sprintf( t('commented on %s\'s post'), $item['owner']['xchan_name']));
|
||||
? (($item['obj_type'] === 'Question') ? t('created a new poll') : t('created a new post'))
|
||||
: (($item['obj_type'] === 'Answer') ? sprintf( t('voted on %s\'s poll'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]') : sprintf( t('commented on %s\'s post'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]'))
|
||||
);
|
||||
|
||||
if($item['verb'] === ACTIVITY_SHARE) {
|
||||
$itemem_text = sprintf( t('repeated %s\'s post'), $item['author']['xchan_name']);
|
||||
$itemem_text = sprintf( t('repeated %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -838,15 +844,16 @@ class Enotify {
|
||||
'addr' => (($item[$who]['xchan_addr']) ? $item[$who]['xchan_addr'] : $item[$who]['xchan_url']),
|
||||
'url' => $item[$who]['xchan_url'],
|
||||
'photo' => $item[$who]['xchan_photo_s'],
|
||||
'when' => relative_date(($edit)? $item['edited'] : $item['created']),
|
||||
'when' => (($edit) ? datetime_convert('UTC', date_default_timezone_get(), $item['edited']) : datetime_convert('UTC', date_default_timezone_get(), $item['created'])),
|
||||
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
|
||||
'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
|
||||
'b64mid' => 'b64.' . base64url_encode($item['mid']),
|
||||
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
|
||||
'notify_id' => 'undefined',
|
||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||
'message' => strip_tags(bbcode($itemem_text)),
|
||||
'message' => bbcode(escape_tags($itemem_text)),
|
||||
// these are for the superblock addon
|
||||
'hash' => $item[$who]['xchan_hash'],
|
||||
'uid' => local_channel(),
|
||||
'uid' => $item['uid'],
|
||||
'display' => true
|
||||
);
|
||||
|
||||
@@ -858,4 +865,120 @@ class Enotify {
|
||||
return $x;
|
||||
}
|
||||
|
||||
static public function format_notify($tt) {
|
||||
|
||||
$message = trim(strip_tags(bbcode($tt['msg'])));
|
||||
|
||||
if(strpos($message, $tt['xname']) === 0)
|
||||
$message = substr($message, strlen($tt['xname']) + 1);
|
||||
|
||||
$mid = basename($tt['link']);
|
||||
|
||||
$b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : 'b64.' . base64url_encode($mid));
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/notify/view/' . $tt['id'],
|
||||
'name' => $tt['xname'],
|
||||
'url' => $tt['url'],
|
||||
'photo' => $tt['photo'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $tt['created']),
|
||||
'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'),
|
||||
'b64mid' => (($tt['otype'] == 'item') ? $b64mid : 'undefined'),
|
||||
'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : 'undefined'),
|
||||
'message' => $message
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_intros($rr) {
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/connections/ifpending',
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
'photo' => $rr['xchan_photo_s'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['abook_created']),
|
||||
'hclass' => ('notify-unseen'),
|
||||
'message' => t('added your channel')
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_files($rr) {
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/sharedwithme',
|
||||
'name' => $rr['author']['xchan_name'],
|
||||
'addr' => $rr['author']['xchan_addr'],
|
||||
'url' => $rr['author']['xchan_url'],
|
||||
'photo' => $rr['author']['xchan_photo_s'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['created']),
|
||||
'hclass' => ('notify-unseen'),
|
||||
'message' => t('shared a file with you')
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_mail($rr) {
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/mail/' . $rr['id'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
'photo' => $rr['xchan_photo_s'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['created']),
|
||||
'hclass' => (intval($rr['mail_seen']) ? 'notify-seen' : 'notify-unseen'),
|
||||
'message' => t('sent you a private message'),
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_all_events($rr) {
|
||||
|
||||
$bd_format = t('g A l F d') ; // 8 AM Friday January 18
|
||||
$strt = datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart']);
|
||||
$today = ((substr($strt, 0, 10) === datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d')) ? true : false);
|
||||
$when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
'photo' => $rr['xchan_photo_s'],
|
||||
'when' => $when,
|
||||
'hclass' => ('notify-unseen'),
|
||||
'message' => t('posted an event')
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_register($rr) {
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/admin/accounts',
|
||||
'name' => $rr['account_email'],
|
||||
'addr' => $rr['account_email'],
|
||||
'url' => '',
|
||||
'photo' => z_root() . '/' . get_default_profile_photo(48),
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(),$rr['account_created']),
|
||||
'hclass' => ('notify-unseen'),
|
||||
'message' => t('requires approval')
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class LDSignatures {
|
||||
'type' => 'RsaSignature2017',
|
||||
'nonce' => random_string(64),
|
||||
'creator' => z_root() . '/channel/' . $channel['channel_address'],
|
||||
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\Th:i:s\Z')
|
||||
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\TH:i:s\Z')
|
||||
];
|
||||
|
||||
$ohash = self::hash(self::signable_options($options));
|
||||
|
||||
@@ -83,7 +83,7 @@ class Libsync {
|
||||
|
||||
$info = (($packet) ? $packet : array());
|
||||
$info['type'] = 'sync';
|
||||
$info['encoding'] = 'red'; // note: not zot, this packet is very platform specific
|
||||
$info['encoding'] = 'hz'; // note: not zot, this packet is very platform specific
|
||||
$info['relocate'] = ['channel_address' => $channel['channel_address'], 'url' => z_root() ];
|
||||
|
||||
if(array_key_exists($uid,\App::$config) && array_key_exists('transient',\App::$config[$uid])) {
|
||||
@@ -144,7 +144,7 @@ class Libsync {
|
||||
|
||||
foreach($synchubs as $hub) {
|
||||
$hash = random_string();
|
||||
$n = Libzot::build_packet($channel,'sync',$env_recips,json_encode($info),'red',$hub['hubloc_sitekey'],$hub['site_crypto']);
|
||||
$n = Libzot::build_packet($channel,'sync',$env_recips,json_encode($info),'hz',$hub['hubloc_sitekey'],$hub['site_crypto']);
|
||||
Queue::insert(array(
|
||||
'hash' => $hash,
|
||||
'account_id' => $channel['channel_account_id'],
|
||||
@@ -244,7 +244,13 @@ class Libsync {
|
||||
|
||||
if(array_key_exists('app',$arr) && $arr['app'])
|
||||
sync_apps($channel,$arr['app']);
|
||||
|
||||
|
||||
if(array_key_exists('addressbook',$arr) && $arr['addressbook'])
|
||||
sync_addressbook($channel,$arr['addressbook']);
|
||||
|
||||
if(array_key_exists('calendar',$arr) && $arr['calendar'])
|
||||
sync_calendar($channel,$arr['calendar']);
|
||||
|
||||
if(array_key_exists('chatroom',$arr) && $arr['chatroom'])
|
||||
sync_chatrooms($channel,$arr['chatroom']);
|
||||
|
||||
|
||||
@@ -1220,12 +1220,42 @@ class Libzot {
|
||||
$arr['owner_xchan'] = $env['sender'];
|
||||
}
|
||||
|
||||
if($private) {
|
||||
$arr['item_private'] = true;
|
||||
if ($private && (! intval($arr['item_private']))) {
|
||||
$arr['item_private'] = 1;
|
||||
}
|
||||
|
||||
if ($arr['mid'] === $arr['parent_mid']) {
|
||||
if (is_array($AS->obj) && array_key_exists('commentPolicy',$AS->obj)) {
|
||||
$p = strstr($AS->obj['commentPolicy'],'until=');
|
||||
if($p !== false) {
|
||||
$arr['comments_closed'] = datetime_convert('UTC','UTC', substr($p,6));
|
||||
$arr['comment_policy'] = trim(str_replace($p,'',$AS->obj['commentPolicy']));
|
||||
}
|
||||
else {
|
||||
$arr['comment_policy'] = $AS->obj['commentPolicy'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @FIXME - spoofable
|
||||
if($AS->data['hubloc']) {
|
||||
$arr['item_verified'] = true;
|
||||
|
||||
if (! array_key_exists('comment_policy',$arr)) {
|
||||
// set comment policy depending on source hub. Unknown or osada is ActivityPub.
|
||||
// Anything else we'll say is zot - which could have a range of project names
|
||||
$s = q("select site_project from site where site_url = '%s' limit 1",
|
||||
dbesc($r[0]['hubloc_url'])
|
||||
);
|
||||
|
||||
if ((! $s) || (in_array($s[0]['site_project'],[ '', 'osada' ]))) {
|
||||
$arr['comment_policy'] = 'authenticated';
|
||||
}
|
||||
else {
|
||||
$arr['comment_policy'] = 'contacts';
|
||||
}
|
||||
}
|
||||
}
|
||||
if($AS->data['signed_data']) {
|
||||
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
|
||||
@@ -1247,7 +1277,12 @@ class Libzot {
|
||||
logger('Channel sync received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
|
||||
logger('Channel sync recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
$result = Libsync::process_channel_sync_delivery($env['sender'],$arr,$deliveries);
|
||||
if ($env['encoding'] === 'hz') {
|
||||
$result = Libsync::process_channel_sync_delivery($env['sender'],$arr,$deliveries);
|
||||
}
|
||||
else {
|
||||
logger('sync packet type not supported.');
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($result) {
|
||||
@@ -1578,10 +1613,11 @@ class Libzot {
|
||||
// As a side effect we will also do a preliminary check that we have the top-level-post, otherwise
|
||||
// processing it is pointless.
|
||||
|
||||
$r = q("select route, id, owner_xchan, item_private from item where mid = '%s' and uid = %d limit 1",
|
||||
$r = q("select route, id, parent_mid, mid, owner_xchan, item_private, obj_type from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($arr['parent_mid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
$DR->update('comment parent not found');
|
||||
$result[] = $DR->get();
|
||||
@@ -1604,6 +1640,16 @@ class Libzot {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($r[0]['obj_type'] === 'Question') {
|
||||
// route checking doesn't work correctly here because we've changed the privacy
|
||||
$r[0]['route'] = EMPTY_STR;
|
||||
// If this is a poll response, convert the obj_type to our (internal-only) "Answer" type
|
||||
if ($arr['obj_type'] === ACTIVITY_OBJ_COMMENT && $arr['title'] && (! $arr['body'])) {
|
||||
$arr['obj_type'] = 'Answer';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($relay || $friendofriend || (intval($r[0]['item_private']) === 0 && intval($arr['item_private']) === 0)) {
|
||||
// reset the route in case it travelled a great distance upstream
|
||||
// use our parent's route so when we go back downstream we'll match
|
||||
@@ -1734,7 +1780,7 @@ class Libzot {
|
||||
// if it's a sourced post, call the post_local hooks as if it were
|
||||
// posted locally so that crosspost connectors will be triggered.
|
||||
|
||||
if(check_item_source($arr['uid'], $arr)) {
|
||||
if(check_item_source($arr['uid'], $arr) || ($channel['xchan_pubforum'] == 1)) {
|
||||
/**
|
||||
* @hooks post_local
|
||||
* Called when an item has been posted on this machine via mod/item.php (also via API).
|
||||
@@ -1819,6 +1865,10 @@ class Libzot {
|
||||
|
||||
$ret = [];
|
||||
|
||||
$signer = q("select hubloc_hash, hubloc_url from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($a['signature']['signer'])
|
||||
);
|
||||
|
||||
foreach($a['data']['orderedItems'] as $activity) {
|
||||
|
||||
$AS = new ActivityStreams($activity);
|
||||
@@ -1877,6 +1927,23 @@ class Libzot {
|
||||
if($AS->data['hubloc']) {
|
||||
$arr['item_verified'] = true;
|
||||
}
|
||||
|
||||
// set comment policy depending on source hub. Unknown or osada is ActivityPub.
|
||||
// Anything else we'll say is zot - which could have a range of project names
|
||||
|
||||
if ($signer) {
|
||||
$s = q("select site_project from site where site_url = '%s' limit 1",
|
||||
dbesc($signer[0]['hubloc_url'])
|
||||
);
|
||||
if ((! $s) || (in_array($s[0]['site_project'],[ '', 'osada' ]))) {
|
||||
$arr['comment_policy'] = 'authenticated';
|
||||
}
|
||||
else {
|
||||
$arr['comment_policy'] = 'contacts';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($AS->data['signed_data']) {
|
||||
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ class Queue {
|
||||
$host_crypto = null;
|
||||
|
||||
if($channel && $base) {
|
||||
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' order by hubloc_id desc limit 1",
|
||||
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' and hubloc_sitekey != '' order by hubloc_id desc limit 1",
|
||||
dbesc($base)
|
||||
);
|
||||
if($h) {
|
||||
|
||||
150
Zotlabs/Lib/SvgSanitizer.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
use DomDocument;
|
||||
|
||||
/**
|
||||
* SVGSantiizer
|
||||
*
|
||||
* Whitelist-based PHP SVG sanitizer.
|
||||
*
|
||||
* @link https://github.com/alister-/SVG-Sanitizer}
|
||||
* @author Alister Norris
|
||||
* @copyright Copyright (c) 2013 Alister Norris
|
||||
* @license http://opensource.org/licenses/mit-license.php The MIT License
|
||||
* @package svgsanitizer
|
||||
*/
|
||||
|
||||
class SvgSanitizer {
|
||||
|
||||
private $xmlDoc; // PHP XML DOMDocument
|
||||
|
||||
private $removedattrs = [];
|
||||
|
||||
private static $allowed_functions = [ 'matrix', 'url', 'translate', 'rgb' ];
|
||||
|
||||
// defines the whitelist of elements and attributes allowed.
|
||||
private static $whitelist = [
|
||||
'a' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'href', 'xlink:href', 'xlink:title' ],
|
||||
'circle' => [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'clipPath' => [ 'class', 'clipPathUnits', 'id' ],
|
||||
'defs' => [ ],
|
||||
'style' => [ 'type' ],
|
||||
'desc' => [ ],
|
||||
'ellipse' => [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'feGaussianBlur' => [ 'class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation' ],
|
||||
'filter' => [ 'class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y' ],
|
||||
'foreignObject' => [ 'class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y' ],
|
||||
'g' => [ 'class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor' ],
|
||||
'image' => [ 'class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y' ],
|
||||
'line' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2' ],
|
||||
'linearGradient' => [ 'class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2' ],
|
||||
'marker' => [ 'id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox' ],
|
||||
'mask' => [ 'class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y' ],
|
||||
'metadata' => [ 'class', 'id' ],
|
||||
'path' => [ 'class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'pattern' => [ 'class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y' ],
|
||||
'polygon' => [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'polyline' => [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'radialGradient' => [ 'class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href' ],
|
||||
'rect' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y' ],
|
||||
'stop' => [ 'class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage' ],
|
||||
'svg' => [ 'class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y' ],
|
||||
'switch' => [ 'class', 'id', 'requiredFeatures', 'systemLanguage' ],
|
||||
'symbol' => [ 'class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox' ],
|
||||
'text' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y' ],
|
||||
'textPath' => [ 'class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href' ],
|
||||
'title' => [ ],
|
||||
'tspan' => [ 'class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y' ],
|
||||
'use' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y' ],
|
||||
];
|
||||
|
||||
function __construct() {
|
||||
$this->xmlDoc = new DOMDocument('1.0','UTF-8');
|
||||
$this->xmlDoc->preserveWhiteSpace = false;
|
||||
libxml_use_internal_errors(true);
|
||||
}
|
||||
|
||||
// load XML SVG
|
||||
function load($file) {
|
||||
$this->xmlDoc->load($file);
|
||||
}
|
||||
|
||||
function loadXML($str) {
|
||||
if (! $this->xmlDoc->loadXML($str)) {
|
||||
logger('loadxml: ' . print_r(libxml_get_errors(),true), LOGGER_DEBUG);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function sanitize()
|
||||
{
|
||||
// all elements in xml doc
|
||||
$allElements = $this->xmlDoc->getElementsByTagName('*');
|
||||
|
||||
// loop through all elements
|
||||
for($i = 0; $i < $allElements->length; $i++)
|
||||
{
|
||||
$this->removedattrs = [];
|
||||
|
||||
$currentNode = $allElements->item($i);
|
||||
|
||||
// logger('current_node: ' . print_r($currentNode,true));
|
||||
|
||||
// array of allowed attributes in specific element
|
||||
$whitelist_attr_arr = self::$whitelist[$currentNode->tagName];
|
||||
|
||||
// does element exist in whitelist?
|
||||
if(isset($whitelist_attr_arr)) {
|
||||
$total = $currentNode->attributes->length;
|
||||
|
||||
for($x = 0; $x < $total; $x++) {
|
||||
|
||||
// get attributes name
|
||||
$attrName = $currentNode->attributes->item($x)->nodeName;
|
||||
|
||||
// logger('checking: ' . print_r($currentNode->attributes->item($x),true));
|
||||
$matches = false;
|
||||
|
||||
// check if attribute isn't in whitelist
|
||||
if(! in_array($attrName, $whitelist_attr_arr)) {
|
||||
$this->removedattrs[] = $attrName;
|
||||
}
|
||||
// check for disallowed functions
|
||||
elseif (preg_match_all('/([a-zA-Z0-9]+)[\s]*\(/',
|
||||
$currentNode->attributes->item($x)->textContent,$matches,PREG_SET_ORDER)) {
|
||||
if ($attrName === 'text') {
|
||||
continue;
|
||||
}
|
||||
foreach ($matches as $match) {
|
||||
if(! in_array($match[1],self::$allowed_functions)) {
|
||||
logger('queue_remove_function: ' . $match[1],LOGGER_DEBUG);
|
||||
$this->removedattrs[] = $attrName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->removedattrs) {
|
||||
foreach ($this->removedattrs as $attr) {
|
||||
$currentNode->removeAttribute($attr);
|
||||
logger('removed: ' . $attr, LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// else remove element
|
||||
else {
|
||||
logger('remove_node: ' . print_r($currentNode,true));
|
||||
$currentNode->parentNode->removeChild($currentNode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function saveSVG() {
|
||||
$this->xmlDoc->formatOutput = true;
|
||||
return($this->xmlDoc->saveXML());
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,14 @@ namespace Zotlabs\Lib;
|
||||
class System {
|
||||
|
||||
static public function get_platform_name() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && array_key_exists('platform_name',\App::$config['system']))
|
||||
return \App::$config['system']['platform_name'];
|
||||
return PLATFORM_NAME;
|
||||
static $platform_name = '';
|
||||
if(empty($platform_name)) {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && array_key_exists('platform_name',\App::$config['system']))
|
||||
$platform_name = \App::$config['system']['platform_name'];
|
||||
else
|
||||
$platform_name = PLATFORM_NAME;
|
||||
}
|
||||
return $platform_name;
|
||||
}
|
||||
|
||||
static public function get_site_name() {
|
||||
|
||||
@@ -78,7 +78,7 @@ class ThreadItem {
|
||||
*/
|
||||
|
||||
public function get_template_data($conv_responses, $thread_level=1, $conv_flags = []) {
|
||||
|
||||
|
||||
$result = array();
|
||||
|
||||
$item = $this->get_data();
|
||||
@@ -95,7 +95,7 @@ class ThreadItem {
|
||||
$total_children = $this->count_descendants();
|
||||
$unseen_comments = (($item['real_uid']) ? 0 : $this->count_unseen_descendants());
|
||||
|
||||
$conv = $this->get_conversation();
|
||||
$conv = $this->get_conversation();
|
||||
$observer = $conv->get_observer();
|
||||
|
||||
$lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|
||||
@@ -204,6 +204,10 @@ class ThreadItem {
|
||||
}
|
||||
}
|
||||
|
||||
if($item['obj_type'] === 'Question') {
|
||||
$response_verbs[] = 'answer';
|
||||
}
|
||||
|
||||
$consensus = (intval($item['item_consensus']) ? true : false);
|
||||
if($consensus) {
|
||||
$response_verbs[] = 'agree';
|
||||
@@ -346,7 +350,7 @@ class ThreadItem {
|
||||
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode(gen_link_id($item['mid']));
|
||||
|
||||
$comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
|
||||
$list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : '');
|
||||
$list_unseen_txt = (($unseen_comments) ? sprintf( t('%d unseen'),$unseen_comments) : '');
|
||||
|
||||
$children = $this->get_children();
|
||||
|
||||
@@ -356,11 +360,28 @@ class ThreadItem {
|
||||
call_hooks('dropdown_extras',$dropdown_extras_arr);
|
||||
$dropdown_extras = $dropdown_extras_arr['dropdown_extras'];
|
||||
|
||||
$midb64 = 'b64.' . base64url_encode($item['mid']);
|
||||
$mids = [ $midb64 ];
|
||||
$response_mids = [];
|
||||
foreach($response_verbs as $v) {
|
||||
if(isset($conv_responses[$v]['mids'][$item['mid']])) {
|
||||
$response_mids = array_merge($response_mids, $conv_responses[$v]['mids'][$item['mid']]);
|
||||
}
|
||||
}
|
||||
|
||||
$mids = array_merge($mids, $response_mids);
|
||||
$json_mids = json_encode($mids);
|
||||
|
||||
// Pinned item processing
|
||||
$allowed_type = (in_array($item['item_type'], get_config('system', 'pin_types', [ ITEM_TYPE_POST ])) ? true : false);
|
||||
$pinned_items = ($allowed_type ? get_pconfig($item['uid'], 'pinned', $item['item_type'], []) : []);
|
||||
$pinned = ((!empty($pinned_items) && in_array($midb64, $pinned_items)) ? true : false);
|
||||
|
||||
$tmp_item = array(
|
||||
'template' => $this->get_template(),
|
||||
'mode' => $mode,
|
||||
'item_type' => intval($item['item_type']),
|
||||
'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
|
||||
//'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
|
||||
'body' => $body['html'],
|
||||
'tags' => $body['tags'],
|
||||
'categories' => $body['categories'],
|
||||
@@ -369,7 +390,8 @@ class ThreadItem {
|
||||
'folders' => $body['folders'],
|
||||
'text' => strip_tags($body['html']),
|
||||
'id' => $this->get_id(),
|
||||
'mid' => $item['mid'],
|
||||
'mid' => $midb64,
|
||||
'mids' => $json_mids,
|
||||
'parent' => $item['parent'],
|
||||
'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
|
||||
'isevent' => $isevent,
|
||||
@@ -377,8 +399,8 @@ class ThreadItem {
|
||||
'consensus' => $consensus,
|
||||
'conlabels' => $conlabels,
|
||||
'canvote' => $canvote,
|
||||
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url'])),
|
||||
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), (($item['owner']['xchan_addr']) ? $item['owner']['xchan_addr'] : $item['owner']['xchan_url'])),
|
||||
'linktitle' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
|
||||
'olinktitle' => (($item['owner']['xchan_addr']) ? $item['owner']['xchan_addr'] : $item['owner']['xchan_url']),
|
||||
'llink' => $item['llink'],
|
||||
'viewthread' => $viewthread,
|
||||
'to' => t('to'),
|
||||
@@ -396,7 +418,7 @@ class ThreadItem {
|
||||
'sparkle' => $sparkle,
|
||||
'title' => $item['title'],
|
||||
'title_tosource' => get_pconfig($conv->get_profile_owner(),'system','title_tosource'),
|
||||
'ago' => relative_date($item['created']),
|
||||
//'ago' => relative_date($item['created']),
|
||||
'app' => $item['app'],
|
||||
'str_app' => sprintf( t('from %s'), $item['app']),
|
||||
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
|
||||
@@ -437,6 +459,9 @@ class ThreadItem {
|
||||
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts') && ($item['item_type'] == ITEM_TYPE_POST)) ? $star : ''),
|
||||
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
|
||||
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing') && ($item['item_type'] == ITEM_TYPE_POST)) ? $filer : ''),
|
||||
'pinned' => ($pinned ? t('Pinned post') : ''),
|
||||
'pinnable' => (($this->is_toplevel() && local_channel() && $item['owner_xchan'] == $observer['xchan_hash'] && $allowed_type && $item['item_private'] == 0) ? '1' : ''),
|
||||
'pinme' => ($pinned ? t('Unpin from the top') : t('Pin to the top')),
|
||||
'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''),
|
||||
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
|
||||
'drop' => $drop,
|
||||
@@ -467,10 +492,9 @@ class ThreadItem {
|
||||
'previewing' => ($conv->is_preview() ? true : false ),
|
||||
'preview_lbl' => t('This is an unsaved preview'),
|
||||
'wait' => t('Please wait'),
|
||||
'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])),
|
||||
'thread_level' => $thread_level,
|
||||
'settings' => $settings,
|
||||
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? $item['thr_parent'] : '')
|
||||
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? 'b64.' . base64url_encode($item['thr_parent']) : '')
|
||||
);
|
||||
|
||||
$arr = array('item' => $item, 'output' => $tmp_item);
|
||||
@@ -778,8 +802,6 @@ class ThreadItem {
|
||||
call_hooks('comment_buttons',$arr);
|
||||
$comment_buttons = $arr['comment_buttons'];
|
||||
|
||||
$feature_auto_save_draft = ((feature_enabled($conv->get_profile_owner(), 'auto_save_draft')) ? "true" : "false");
|
||||
|
||||
$comment_box = replace_macros($template,array(
|
||||
'$return_path' => '',
|
||||
'$threaded' => $this->is_threaded(),
|
||||
@@ -814,8 +836,7 @@ class ThreadItem {
|
||||
'$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false),
|
||||
'$anonname' => [ 'anonname', t('Your full name (required)') ],
|
||||
'$anonmail' => [ 'anonmail', t('Your email address (required)') ],
|
||||
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ],
|
||||
'$auto_save_draft' => $feature_auto_save_draft
|
||||
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ]
|
||||
));
|
||||
|
||||
return $comment_box;
|
||||
@@ -866,7 +887,4 @@ class ThreadItem {
|
||||
return $this->visiting;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
// $type =
|
||||
// 'm' => autocomplete private mail recipient (checks post_mail permission)
|
||||
// 'm' => autocomplete private mail recipient (checks post_mail permission and displays only zot, diaspora, friendica-over-diaspora xchan_network xchan's)
|
||||
// 'a' => autocomplete connections (mod_connections, mod_poke, mod_sources, mod_photos)
|
||||
// 'x' => nav search bar autocomplete (match any xchan)
|
||||
// $_REQUEST['query'] contains autocomplete search text.
|
||||
@@ -286,6 +286,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d
|
||||
and xchan_deleted = 0
|
||||
and xchan_network IN ('zot', 'diaspora', 'friendica-over-diaspora')
|
||||
$sql_extra3
|
||||
ORDER BY xchan_name ASC ",
|
||||
intval(local_channel())
|
||||
|
||||
175
Zotlabs/Module/Activity.php
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\IConfig;
|
||||
use Zotlabs\Lib\Enotify;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Activity as ZlibActivity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\ThreadListener;
|
||||
use App;
|
||||
|
||||
|
||||
class Activity extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if (Libzot::is_zot_request()) {
|
||||
|
||||
$item_id = argv(1);
|
||||
|
||||
if (! $item_id)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$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 ";
|
||||
|
||||
$i = null;
|
||||
|
||||
// do we have the item (at all)?
|
||||
|
||||
$r = q("select * from item where mid = '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/activity/' . $item_id)
|
||||
);
|
||||
|
||||
if (! $r) {
|
||||
http_status_exit(404,'Not found');
|
||||
}
|
||||
|
||||
// process an authenticated fetch
|
||||
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$portable_id = $sigdata['portable_id'];
|
||||
observer_auth($portable_id);
|
||||
|
||||
// first see if we have a copy of this item's parent owned by the current signer
|
||||
// include xchans for all zot-like networks - these will have the same guid and public key
|
||||
|
||||
$x = q("select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($sigdata['portable_id'])
|
||||
);
|
||||
|
||||
if ($x) {
|
||||
$xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ",
|
||||
dbesc($sigdata['portable_id']),
|
||||
dbesc($x[0]['xchan_guid']),
|
||||
dbesc($x[0]['xchan_pubkey'])
|
||||
);
|
||||
|
||||
if ($xchans) {
|
||||
$hashes = ids_to_querystr($xchans,'xchan_hash',true);
|
||||
$i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1",
|
||||
dbesc($r[0]['parent_mid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
|
||||
// with a bias towards those items owned by channels on this site (item_wall = 1)
|
||||
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
|
||||
if (! $i) {
|
||||
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
|
||||
dbesc($r[0]['parent_mid'])
|
||||
);
|
||||
}
|
||||
|
||||
if(! $i) {
|
||||
http_status_exit(403,'Forbidden');
|
||||
}
|
||||
|
||||
$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)
|
||||
);
|
||||
|
||||
if(! $items) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
xchan_query($items,true);
|
||||
$items = fetch_post_tags($items,true);
|
||||
|
||||
$observer = App::get_observer();
|
||||
$parent = $items[0];
|
||||
$recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'],'activitypub','recips', []) : []);
|
||||
$to = (($recips && array_key_exists('to',$recips) && is_array($recips['to'])) ? $recips['to'] : null);
|
||||
$nitems = [];
|
||||
foreach($items as $i) {
|
||||
|
||||
$mids = [];
|
||||
|
||||
if(intval($i['item_private'])) {
|
||||
if(! $observer) {
|
||||
continue;
|
||||
}
|
||||
// ignore private reshare, possibly from hubzilla
|
||||
if($i['verb'] === 'Announce') {
|
||||
if(! in_array($i['thr_parent'],$mids)) {
|
||||
$mids[] = $i['thr_parent'];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// also ignore any children of the private reshares
|
||||
if(in_array($i['thr_parent'],$mids)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if((! $to) || (! in_array($observer['xchan_url'],$to))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
$nitems[] = $i;
|
||||
}
|
||||
|
||||
if(! $nitems)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$chan = channelx_by_n($nitems[0]['uid']);
|
||||
|
||||
if(! $chan)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
|
||||
http_status_exit(403, 'Forbidden');
|
||||
|
||||
$i = ZlibActivity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection');
|
||||
if($portable_id) {
|
||||
ThreadListener::store(z_root() . '/activity/' . $item_id,$portable_id);
|
||||
}
|
||||
|
||||
if(! $i)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], $i);
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/x-zot+json' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$chan);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Module\Admin;
|
||||
|
||||
use App;
|
||||
use \Zotlabs\Storage\GitRepo;
|
||||
use \Michelf\MarkdownExtra;
|
||||
|
||||
@@ -253,14 +254,14 @@ class Addons {
|
||||
* Single plugin
|
||||
*/
|
||||
|
||||
if (\App::$argc == 3){
|
||||
$plugin = \App::$argv[2];
|
||||
if (App::$argc == 3){
|
||||
$plugin = App::$argv[2];
|
||||
if (!is_file("addon/$plugin/$plugin.php")){
|
||||
notice( t("Item not found.") );
|
||||
return '';
|
||||
}
|
||||
|
||||
$enabled = in_array($plugin,\App::$plugins);
|
||||
$enabled = in_array($plugin,App::$plugins);
|
||||
$info = get_plugin_info($plugin);
|
||||
$x = check_plugin_versions($info);
|
||||
|
||||
@@ -268,11 +269,11 @@ class Addons {
|
||||
|
||||
if($enabled && ! $x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($plugin, \App::$plugins);
|
||||
$idz = array_search($plugin, App::$plugins);
|
||||
if ($idz !== false) {
|
||||
unset(\App::$plugins[$idz]);
|
||||
unset(App::$plugins[$idz]);
|
||||
uninstall_plugin($plugin);
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
set_config("system","addon", implode(", ",App::$plugins));
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1-intval($x);
|
||||
@@ -281,19 +282,19 @@ class Addons {
|
||||
check_form_security_token_redirectOnErr('/admin/addons', 'admin_addons', 't');
|
||||
$pinstalled = false;
|
||||
// Toggle plugin status
|
||||
$idx = array_search($plugin, \App::$plugins);
|
||||
$idx = array_search($plugin, App::$plugins);
|
||||
if ($idx !== false){
|
||||
unset(\App::$plugins[$idx]);
|
||||
unset(App::$plugins[$idx]);
|
||||
uninstall_plugin($plugin);
|
||||
$pinstalled = false;
|
||||
info( sprintf( t("Plugin %s disabled."), $plugin ) );
|
||||
} else {
|
||||
\App::$plugins[] = $plugin;
|
||||
App::$plugins[] = $plugin;
|
||||
install_plugin($plugin);
|
||||
$pinstalled = true;
|
||||
info( sprintf( t("Plugin %s enabled."), $plugin ) );
|
||||
}
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
set_config("system","addon", implode(", ",App::$plugins));
|
||||
|
||||
if($pinstalled) {
|
||||
@require_once("addon/$plugin/$plugin.php");
|
||||
@@ -305,7 +306,7 @@ class Addons {
|
||||
|
||||
// display plugin details
|
||||
|
||||
if (in_array($plugin, \App::$plugins)){
|
||||
if (in_array($plugin, App::$plugins)){
|
||||
$status = 'on';
|
||||
$action = t('Disable');
|
||||
} else {
|
||||
@@ -380,18 +381,18 @@ class Addons {
|
||||
|
||||
list($tmp, $id) = array_map('trim', explode('/', $file));
|
||||
$info = get_plugin_info($id);
|
||||
$enabled = in_array($id,\App::$plugins);
|
||||
$enabled = in_array($id,App::$plugins);
|
||||
$x = check_plugin_versions($info);
|
||||
|
||||
// disable plugins which are installed but incompatible versions
|
||||
|
||||
if($enabled && ! $x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($id, \App::$plugins);
|
||||
$idz = array_search($id, App::$plugins);
|
||||
if ($idz !== false) {
|
||||
unset(\App::$plugins[$idz]);
|
||||
unset(App::$plugins[$idz]);
|
||||
uninstall_plugin($id);
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
set_config("system","addon", implode(", ",App::$plugins));
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1-intval($x);
|
||||
|
||||
@@ -43,6 +43,12 @@ class Security {
|
||||
|
||||
$be = $this->trim_array_elems(explode("\n",$_POST['embed_deny']));
|
||||
set_config('system','embed_deny',$be);
|
||||
|
||||
$thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0);
|
||||
set_config('system', 'thumbnail_security' , $thumbnail_security);
|
||||
|
||||
$inline_pdf = ((x($_POST,'inline_pdf')) ? intval($_POST['inline_pdf']) : 0);
|
||||
set_config('system', 'inline_pdf' , $inline_pdf);
|
||||
|
||||
$ts = ((x($_POST,'transport_security')) ? True : False);
|
||||
set_config('system','transport_security_header',$ts);
|
||||
@@ -86,7 +92,7 @@ class Security {
|
||||
$embedhelp2 = t("The recommended setting is to only allow unfiltered HTML from the following sites:");
|
||||
$embedhelp3 = t("https://youtube.com/<br />https://www.youtube.com/<br />https://youtu.be/<br />https://vimeo.com/<br />https://soundcloud.com/<br />");
|
||||
$embedhelp4 = t("All other embedded content will be filtered, <strong>unless</strong> embedded content from that site is explicitly blocked.");
|
||||
|
||||
|
||||
$t = get_markup_template('admin_security.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
@@ -106,7 +112,9 @@ class Security {
|
||||
'$embed_sslonly' => array('embed_sslonly',t('Only allow embeds from secure (SSL) websites and links.'), intval(get_config('system','embed_sslonly')),''),
|
||||
'$embed_allow' => array('embed_allow', t('Allow unfiltered embedded HTML content only from these domains'), $whiteembeds_str, t('One site per line. By default embedded content is filtered.')),
|
||||
'$embed_deny' => array('embed_deny', t('Block embedded HTML from these domains'), $blackembeds_str, ''),
|
||||
|
||||
'$thumbnail_security' => [ 'thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.") ],
|
||||
'$inline_pdf' => [ 'inline_pdf', t("Allow embedded (inline) PDF files"), get_config('system','inline_pdf',0), '' ],
|
||||
|
||||
// '$embed_coop' => array('embed_coop', t('Cooperative embed security'), $embed_coop, t('Enable to share embed security with other compatible sites/hubs')),
|
||||
|
||||
'$submit' => t('Submit')
|
||||
@@ -128,4 +136,4 @@ class Security {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ class Site {
|
||||
$feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
|
||||
$verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
|
||||
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
|
||||
$thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0);
|
||||
$force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000);
|
||||
$pub_incl = escape_tags(trim($_POST['pub_incl']));
|
||||
$pub_excl = escape_tags(trim($_POST['pub_excl']));
|
||||
@@ -100,7 +99,6 @@ class Site {
|
||||
set_config('system', 'from_email', $from_email);
|
||||
set_config('system', 'from_email_name' , $from_email_name);
|
||||
set_config('system', 'imagick_convert_path' , $imagick_path);
|
||||
set_config('system', 'thumbnail_security' , $thumbnail_security);
|
||||
set_config('system', 'default_permissions_role', $permissions_role);
|
||||
set_config('system', 'pubstream_incl',$pub_incl);
|
||||
set_config('system', 'pubstream_excl',$pub_excl);
|
||||
@@ -341,7 +339,6 @@ class Site {
|
||||
'$force_queue' => array('force_queue', t("Queue Threshold"), get_config('system','force_queue_threshold',3000), t("Always defer immediate delivery if queue contains more than this number of entries.")),
|
||||
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
|
||||
'$imagick_path' => array('imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert")),
|
||||
'$thumbnail_security' => array('thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.")),
|
||||
'$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)), ''),
|
||||
|
||||
@@ -85,10 +85,9 @@ 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'];
|
||||
|
||||
$x = array(
|
||||
@@ -110,7 +109,7 @@ class Article_edit extends \Zotlabs\Web\Controller {
|
||||
'ptyp' => $itm[0]['type'],
|
||||
'mimeselect' => false,
|
||||
'mimetype' => $itm[0]['mimetype'],
|
||||
'body' => undo_post_tagging($content),
|
||||
'body' => $summary . undo_post_tagging($content),
|
||||
'post_id' => $post_id,
|
||||
'visitor' => true,
|
||||
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
|
||||
|
||||
@@ -9,6 +9,7 @@ use Zotlabs\Lib\PermissionDescription;
|
||||
require_once('include/channel.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/opengraph.php');
|
||||
|
||||
|
||||
class Articles extends Controller {
|
||||
@@ -192,7 +193,7 @@ class Articles extends Controller {
|
||||
|
||||
$parents_str = ids_to_querystr($r,'id');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
$r = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE item.uid = %d $item_normal
|
||||
AND item.parent IN ( %s )
|
||||
@@ -200,15 +201,18 @@ class Articles extends Controller {
|
||||
intval(App::$profile['profile_uid']),
|
||||
dbesc($parents_str)
|
||||
);
|
||||
if($items) {
|
||||
xchan_query($items);
|
||||
$items = fetch_post_tags($items, true);
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$items = fetch_post_tags($r, true);
|
||||
$items = conv_sort($items,'updated');
|
||||
}
|
||||
else
|
||||
$items = [];
|
||||
}
|
||||
|
||||
// Add Opengraph markup
|
||||
opengraph_add_meta((! empty($items) ? $r[0] : []), $channel);
|
||||
|
||||
$mode = 'articles';
|
||||
|
||||
if(get_pconfig(local_channel(),'system','articles_list_mode') && (! $selected_card))
|
||||
|
||||
@@ -10,6 +10,7 @@ require_once('include/event.php');
|
||||
|
||||
require_once('include/auth.php');
|
||||
require_once('include/security.php');
|
||||
require_once('include/cdav.php');
|
||||
|
||||
class Cdav extends Controller {
|
||||
|
||||
@@ -156,6 +157,79 @@ class Cdav extends Controller {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Track CDAV updates from remote clients
|
||||
|
||||
$httpmethod = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if($httpmethod === 'PUT' || $httpmethod === 'DELETE') {
|
||||
|
||||
$httpuri = $_SERVER['REQUEST_URI'];
|
||||
|
||||
logger("debug: method: " . $httpmethod, LOGGER_DEBUG);
|
||||
logger("debug: uri: " . $httpuri, LOGGER_DEBUG);
|
||||
|
||||
if(strpos($httpuri, 'cdav/addressbooks')) {
|
||||
$sync = 'addressbook';
|
||||
$cdavtable = 'addressbooks';
|
||||
}
|
||||
elseif(strpos($httpuri, 'cdav/calendars')) {
|
||||
$sync = 'calendar';
|
||||
$cdavtable = 'calendarinstances';
|
||||
}
|
||||
else
|
||||
$sync = false;
|
||||
|
||||
if($sync) {
|
||||
|
||||
$uri = basename($httpuri);
|
||||
$httpbody = file_get_contents('php://input');
|
||||
|
||||
logger("debug: body: " . $httpbody, LOGGER_DEBUG);
|
||||
|
||||
if($x = get_cdav_id($principalUri, explode("/", $httpuri)[4], $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)
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'delete_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri
|
||||
]
|
||||
]);
|
||||
else {
|
||||
if($etag) {
|
||||
// update
|
||||
if($cdavdata['etag'] !== $etag)
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $httpbody
|
||||
]
|
||||
]);
|
||||
}
|
||||
else {
|
||||
// new
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'ids' => [ $uri ],
|
||||
'card' => $httpbody
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo);
|
||||
@@ -262,6 +336,14 @@ class Cdav extends Controller {
|
||||
|
||||
// set new calendar to be visible
|
||||
set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'create',
|
||||
'uri' => $calendarUri,
|
||||
'properties' => $properties
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//create new calendar object via ajax request
|
||||
@@ -272,6 +354,8 @@ class Cdav extends Controller {
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
@@ -327,9 +411,17 @@ class Cdav extends Controller {
|
||||
$vcalendar->VEVENT->DTSTART['TZID'] = $tz;
|
||||
|
||||
$calendarData = $vcalendar->serialize();
|
||||
|
||||
$caldavBackend->createCalendarObject($id, $objectUri, $calendarData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'ids' => [ $objectUri ],
|
||||
'card' => $calendarData
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -341,17 +433,24 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id[0],$calendars))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$mutations = [
|
||||
'{DAV:}displayname' => $_REQUEST['{DAV:}displayname'],
|
||||
'{http://apple.com/ns/ical/}calendar-color' => $_REQUEST['color']
|
||||
];
|
||||
|
||||
$patch = new \Sabre\DAV\PropPatch($mutations);
|
||||
|
||||
$caldavBackend->updateCalendar($id, $patch);
|
||||
|
||||
$patch->commit();
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'edit',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'mutations' => $mutations,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//edit calendar object via ajax request
|
||||
@@ -359,9 +458,11 @@ class Cdav extends Controller {
|
||||
|
||||
$id = explode(':', $_REQUEST['target']);
|
||||
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
if(! cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
@@ -407,9 +508,17 @@ class Cdav extends Controller {
|
||||
$vcalendar->VEVENT->LOCATION = $location;
|
||||
|
||||
$calendarData = $vcalendar->serialize();
|
||||
|
||||
$caldavBackend->updateCalendarObject($id, $uri, $calendarData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $calendarData
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -418,13 +527,23 @@ class Cdav extends Controller {
|
||||
|
||||
$id = explode(':', $_REQUEST['target']);
|
||||
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
if(! cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$uri = $_REQUEST['uri'];
|
||||
|
||||
$caldavBackend->deleteCalendarObject($id, $uri);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'delete_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -433,9 +552,11 @@ class Cdav extends Controller {
|
||||
|
||||
$id = [$_REQUEST['id'][0], $_REQUEST['id'][1]];
|
||||
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
if(! cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
@@ -471,9 +592,17 @@ class Cdav extends Controller {
|
||||
unset($vcalendar->VEVENT->DTEND);
|
||||
|
||||
$calendarData = $vcalendar->serialize();
|
||||
|
||||
$caldavBackend->updateCalendarObject($id, $uri, $calendarData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $calendarData
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -523,6 +652,14 @@ class Cdav extends Controller {
|
||||
$properties = ['{DAV:}displayname' => $_REQUEST['{DAV:}displayname']];
|
||||
|
||||
$carddavBackend->createAddressBook($principalUri, $addressbookUri, $properties);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'create',
|
||||
'uri' => $addressbookUri,
|
||||
'properties' => $properties
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//edit addressbook
|
||||
@@ -533,21 +670,32 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id,$addressbooks))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
$mutations = [
|
||||
'{DAV:}displayname' => $_REQUEST['{DAV:}displayname']
|
||||
];
|
||||
|
||||
$patch = new \Sabre\DAV\PropPatch($mutations);
|
||||
|
||||
$carddavBackend->updateAddressBook($id, $patch);
|
||||
|
||||
$patch->commit();
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'edit',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'mutations' => $mutations,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//create addressbook card
|
||||
if($_REQUEST['create'] && $_REQUEST['target'] && $_REQUEST['fn']) {
|
||||
|
||||
$id = $_REQUEST['target'];
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
do {
|
||||
$duplicate = false;
|
||||
$uri = random_string(40) . '.vcf';
|
||||
@@ -569,86 +717,21 @@ class Cdav extends Controller {
|
||||
'N' => array_reverse(explode(' ', $fn))
|
||||
]);
|
||||
|
||||
$org = $_REQUEST['org'];
|
||||
if($org) {
|
||||
$vcard->ORG = $org;
|
||||
}
|
||||
$fields = $this->request_to_array($_REQUEST);
|
||||
|
||||
$title = $_REQUEST['title'];
|
||||
if($title) {
|
||||
$vcard->TITLE = $title;
|
||||
}
|
||||
|
||||
$tel = $_REQUEST['tel'];
|
||||
$tel_type = $_REQUEST['tel_type'];
|
||||
if($tel) {
|
||||
$i = 0;
|
||||
foreach($tel as $item) {
|
||||
if($item) {
|
||||
$vcard->add('TEL', $item, ['type' => $tel_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$email = $_REQUEST['email'];
|
||||
$email_type = $_REQUEST['email_type'];
|
||||
if($email) {
|
||||
$i = 0;
|
||||
foreach($email as $item) {
|
||||
if($item) {
|
||||
$vcard->add('EMAIL', $item, ['type' => $email_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$impp = $_REQUEST['impp'];
|
||||
$impp_type = $_REQUEST['impp_type'];
|
||||
if($impp) {
|
||||
$i = 0;
|
||||
foreach($impp as $item) {
|
||||
if($item) {
|
||||
$vcard->add('IMPP', $item, ['type' => $impp_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$url = $_REQUEST['url'];
|
||||
$url_type = $_REQUEST['url_type'];
|
||||
if($url) {
|
||||
$i = 0;
|
||||
foreach($url as $item) {
|
||||
if($item) {
|
||||
$vcard->add('URL', $item, ['type' => $url_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$adr = $_REQUEST['adr'];
|
||||
$adr_type = $_REQUEST['adr_type'];
|
||||
|
||||
if($adr) {
|
||||
$i = 0;
|
||||
foreach($adr as $item) {
|
||||
if($item) {
|
||||
$vcard->add('ADR', $item, ['type' => $adr_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$note = $_REQUEST['note'];
|
||||
if($note) {
|
||||
$vcard->NOTE = $note;
|
||||
}
|
||||
process_cdav_card($fields, $vcard);
|
||||
|
||||
$cardData = $vcard->serialize();
|
||||
|
||||
$carddavBackend->createCard($id, $uri, $cardData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'ids' => [ $uri ],
|
||||
'card' => $cardData
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//edit addressbook card
|
||||
@@ -656,9 +739,11 @@ class Cdav extends Controller {
|
||||
|
||||
$id = $_REQUEST['target'];
|
||||
|
||||
if(!cdav_perms($id,$addressbooks))
|
||||
if(! cdav_perms($id,$addressbooks))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
$uri = $_REQUEST['uri'];
|
||||
|
||||
$object = $carddavBackend->getCard($id, $uri);
|
||||
@@ -670,113 +755,23 @@ class Cdav extends Controller {
|
||||
$vcard->N = array_reverse(explode(' ', $fn));
|
||||
}
|
||||
|
||||
$org = $_REQUEST['org'];
|
||||
if($org) {
|
||||
$vcard->ORG = $org;
|
||||
}
|
||||
else {
|
||||
unset($vcard->ORG);
|
||||
}
|
||||
$fields = $this->request_to_array($_REQUEST);
|
||||
|
||||
$title = $_REQUEST['title'];
|
||||
if($title) {
|
||||
$vcard->TITLE = $title;
|
||||
}
|
||||
else {
|
||||
unset($vcard->TITLE);
|
||||
}
|
||||
|
||||
$tel = $_REQUEST['tel'];
|
||||
$tel_type = $_REQUEST['tel_type'];
|
||||
if($tel) {
|
||||
$i = 0;
|
||||
unset($vcard->TEL);
|
||||
foreach($tel as $item) {
|
||||
if($item) {
|
||||
$vcard->add('TEL', $item, ['type' => $tel_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->TEL);
|
||||
}
|
||||
|
||||
$email = $_REQUEST['email'];
|
||||
$email_type = $_REQUEST['email_type'];
|
||||
if($email) {
|
||||
$i = 0;
|
||||
unset($vcard->EMAIL);
|
||||
foreach($email as $item) {
|
||||
if($item) {
|
||||
$vcard->add('EMAIL', $item, ['type' => $email_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->EMAIL);
|
||||
}
|
||||
|
||||
$impp = $_REQUEST['impp'];
|
||||
$impp_type = $_REQUEST['impp_type'];
|
||||
if($impp) {
|
||||
$i = 0;
|
||||
unset($vcard->IMPP);
|
||||
foreach($impp as $item) {
|
||||
if($item) {
|
||||
$vcard->add('IMPP', $item, ['type' => $impp_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->IMPP);
|
||||
}
|
||||
|
||||
$url = $_REQUEST['url'];
|
||||
$url_type = $_REQUEST['url_type'];
|
||||
if($url) {
|
||||
$i = 0;
|
||||
unset($vcard->URL);
|
||||
foreach($url as $item) {
|
||||
if($item) {
|
||||
$vcard->add('URL', $item, ['type' => $url_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->URL);
|
||||
}
|
||||
|
||||
$adr = $_REQUEST['adr'];
|
||||
$adr_type = $_REQUEST['adr_type'];
|
||||
if($adr) {
|
||||
$i = 0;
|
||||
unset($vcard->ADR);
|
||||
foreach($adr as $item) {
|
||||
if($item) {
|
||||
$vcard->add('ADR', $item, ['type' => $adr_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->ADR);
|
||||
}
|
||||
|
||||
$note = $_REQUEST['note'];
|
||||
if($note) {
|
||||
$vcard->NOTE = $note;
|
||||
}
|
||||
else {
|
||||
unset($vcard->NOTE);
|
||||
}
|
||||
process_cdav_card($fields, $vcard, true);
|
||||
|
||||
$cardData = $vcard->serialize();
|
||||
|
||||
$carddavBackend->updateCard($id, $uri, $cardData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $cardData
|
||||
]
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
//delete addressbook card
|
||||
@@ -784,12 +779,22 @@ class Cdav extends Controller {
|
||||
|
||||
$id = $_REQUEST['target'];
|
||||
|
||||
if(!cdav_perms($id,$addressbooks))
|
||||
if(! cdav_perms($id,$addressbooks))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
$uri = $_REQUEST['uri'];
|
||||
|
||||
$carddavBackend->deleteCard($id, $uri);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'delete_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -799,6 +804,8 @@ class Cdav extends Controller {
|
||||
$src = $_FILES['userfile']['tmp_name'];
|
||||
|
||||
if($src) {
|
||||
|
||||
$carddata = @file_get_contents($src);
|
||||
|
||||
if($_REQUEST['c_upload']) {
|
||||
if($_REQUEST['target'] == 'channel_calendar') {
|
||||
@@ -812,76 +819,42 @@ class Cdav extends Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$id = explode(':', $_REQUEST['target']);
|
||||
$id = explode(':', $_REQUEST['target'])[0];
|
||||
$ext = 'ics';
|
||||
$table = 'calendarobjects';
|
||||
$column = 'calendarid';
|
||||
$objects = new \Sabre\VObject\Splitter\ICalendar(@file_get_contents($src));
|
||||
$sync = 'calendar';
|
||||
$objects = new \Sabre\VObject\Splitter\ICalendar($carddata);
|
||||
$profile = \Sabre\VObject\Node::PROFILE_CALDAV;
|
||||
$backend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'calendarinstances');
|
||||
}
|
||||
|
||||
if($_REQUEST['a_upload']) {
|
||||
$id[] = intval($_REQUEST['target']);
|
||||
$id = intval($_REQUEST['target']);
|
||||
$ext = 'vcf';
|
||||
$table = 'cards';
|
||||
$column = 'addressbookid';
|
||||
$objects = new \Sabre\VObject\Splitter\VCard(@file_get_contents($src));
|
||||
$sync = 'addressbook';
|
||||
$objects = new \Sabre\VObject\Splitter\VCard($carddata);
|
||||
$profile = \Sabre\VObject\Node::PROFILE_CARDDAV;
|
||||
$backend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
}
|
||||
|
||||
while ($object = $objects->getNext()) {
|
||||
|
||||
if($_REQUEST['a_upload']) {
|
||||
$object = $object->convert(\Sabre\VObject\Document::VCARD40);
|
||||
}
|
||||
|
||||
$ret = $object->validate($profile & \Sabre\VObject\Node::REPAIR);
|
||||
|
||||
//level 3 Means that the document is invalid,
|
||||
//level 2 means a warning. A warning means it's valid but it could cause interopability issues,
|
||||
//level 1 means that there was a problem earlier, but the problem was automatically repaired.
|
||||
|
||||
if($ret[0]['level'] < 3) {
|
||||
do {
|
||||
$duplicate = false;
|
||||
$objectUri = random_string(40) . '.' . $ext;
|
||||
|
||||
$r = q("SELECT uri FROM $table WHERE $column = %d AND uri = '%s' LIMIT 1",
|
||||
dbesc($id[0]),
|
||||
dbesc($objectUri)
|
||||
);
|
||||
|
||||
if (count($r))
|
||||
$duplicate = true;
|
||||
} while ($duplicate == true);
|
||||
|
||||
if($_REQUEST['c_upload']) {
|
||||
$backend->createCalendarObject($id, $objectUri, $object->serialize());
|
||||
}
|
||||
|
||||
if($_REQUEST['a_upload']) {
|
||||
$backend->createCard($id[0], $objectUri, $object->serialize());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if($_REQUEST['c_upload']) {
|
||||
notice( '<strong>' . t('INVALID EVENT DISMISSED!') . '</strong>' . EOL .
|
||||
'<strong>' . t('Summary: ') . '</strong>' . (($object->VEVENT->SUMMARY) ? $object->VEVENT->SUMMARY : t('Unknown')) . EOL .
|
||||
'<strong>' . t('Date: ') . '</strong>' . (($object->VEVENT->DTSTART) ? $object->VEVENT->DTSTART : t('Unknown')) . EOL .
|
||||
'<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL
|
||||
);
|
||||
}
|
||||
|
||||
if($_REQUEST['a_upload']) {
|
||||
notice( '<strong>' . t('INVALID CARD DISMISSED!') . '</strong>' . EOL .
|
||||
'<strong>' . t('Name: ') . '</strong>' . (($object->FN) ? $object->FN : t('Unknown')) . EOL .
|
||||
'<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
import_cdav_card($id, $ext, $table, $column, $objects, $profile, $backend, $ids, true);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'ids' => $ids,
|
||||
'card' => $carddata
|
||||
]
|
||||
]);
|
||||
}
|
||||
@unlink($src);
|
||||
}
|
||||
@@ -910,8 +883,6 @@ class Cdav extends Controller {
|
||||
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
head_add_css('cdav.css');
|
||||
|
||||
if(!cdav_principal($principalUri)) {
|
||||
$this->activate($pdo, $channel);
|
||||
if(!cdav_principal($principalUri)) {
|
||||
@@ -1192,7 +1163,18 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id,$calendars))
|
||||
killme();
|
||||
|
||||
set_pconfig(local_channel(), 'cdav_calendar' , argv(3), argv(4));
|
||||
$cdavdata = $this->get_cdav_data($id, 'calendarinstances');
|
||||
|
||||
set_pconfig(local_channel(), 'cdav_calendar', $id, argv(4));
|
||||
|
||||
build_sync_packet(local_channel(), [
|
||||
'calendar' => [
|
||||
'action' => 'switch',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'switch' => intval(argv(4))
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -1203,7 +1185,18 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id[0],$calendars))
|
||||
killme();
|
||||
|
||||
// get metadata before we delete it
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$caldavBackend->deleteCalendar($id);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'drop',
|
||||
'uri' => $cdavdata['uri']
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -1410,7 +1403,19 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id,$addressbooks))
|
||||
return;
|
||||
|
||||
// get metadata before we delete it
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
$carddavBackend->deleteAddressBook($id);
|
||||
|
||||
if($cdavdata)
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'drop',
|
||||
'uri' => $cdavdata['uri']
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -1462,4 +1467,36 @@ class Cdav extends Controller {
|
||||
}
|
||||
|
||||
|
||||
function get_cdav_data($id, $table) {
|
||||
|
||||
$r = q("SELECT * FROM $table WHERE id = %d LIMIT 1",
|
||||
intval($id)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
return false;
|
||||
|
||||
return $r[0];
|
||||
}
|
||||
|
||||
function request_to_array($req) {
|
||||
|
||||
$f = [];
|
||||
|
||||
$f['org'] = $req['org'];
|
||||
$f['title'] = $req['title'];
|
||||
$f['tel'] = $req['tel'];
|
||||
$f['tel_type'] = $req['tel_type'];
|
||||
$f['email'] = $req['email'];
|
||||
$f['email_type'] = $req['email_type'];
|
||||
$f['impp'] = $req['impp'];
|
||||
$f['impp_type'] = $req['impp_type'];
|
||||
$f['url'] = $req['url'];
|
||||
$f['url_type'] = $req['url_type'];
|
||||
$f['adr'] = $req['adr'];
|
||||
$f['adr_type'] = $req['adr_type'];
|
||||
$f['note'] = $req['note'];
|
||||
|
||||
return $f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ require_once('include/items.php');
|
||||
require_once('include/security.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/opengraph.php');
|
||||
|
||||
|
||||
/**
|
||||
@@ -109,19 +110,20 @@ class Channel extends Controller {
|
||||
|
||||
// Run profile_load() here to make sure the theme is set before
|
||||
// we start loading content
|
||||
|
||||
profile_load($which,$profile);
|
||||
|
||||
App::$page['htmlhead'] .= '<meta property="og:title" content="' . htmlspecialchars($channel['channel_name']) . '">' . "\r\n";
|
||||
App::$page['htmlhead'] .= '<meta property="og:image" content="' . $channel['xchan_photo_l'] . '">' . "\r\n";
|
||||
|
||||
if(App::$profile['about'] && perm_is_allowed($channel['channel_id'],get_observer_hash(),'view_profile')) {
|
||||
App::$page['htmlhead'] .= '<meta property="og:description" content="' . htmlspecialchars(App::$profile['about']) . '">' . "\r\n";
|
||||
}
|
||||
else {
|
||||
App::$page['htmlhead'] .= '<meta property="og:description" content="' . htmlspecialchars(sprintf( t('This is the home page of %s.'), $channel['channel_name'])) . '">' . "\r\n";
|
||||
}
|
||||
|
||||
|
||||
// Add Opengraph markup
|
||||
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
|
||||
if(strpos($mid,'b64.') === 0)
|
||||
$mid = @base64url_decode(substr($mid,4));
|
||||
|
||||
if($mid)
|
||||
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
|
||||
dbesc($mid),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
opengraph_add_meta($r ? $r[0] : [], $channel);
|
||||
}
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
@@ -362,7 +364,7 @@ class Channel extends Controller {
|
||||
|
||||
$parents_str = ids_to_querystr($r,'item_id');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
$r = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE item.uid = %d $item_normal
|
||||
AND item.parent IN ( %s )
|
||||
@@ -371,8 +373,8 @@ class Channel extends Controller {
|
||||
dbesc($parents_str)
|
||||
);
|
||||
|
||||
xchan_query($items);
|
||||
$items = fetch_post_tags($items, true);
|
||||
xchan_query($r);
|
||||
$items = fetch_post_tags($r, true);
|
||||
$items = conv_sort($items,$ordering);
|
||||
|
||||
if($load && $mid && (! count($items))) {
|
||||
@@ -417,6 +419,7 @@ class Channel extends Controller {
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '1',
|
||||
'$fh' => '0',
|
||||
'$dm' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
|
||||
'$search' => $search,
|
||||
@@ -466,6 +469,13 @@ class Channel extends Controller {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add pinned content
|
||||
if(! x($_REQUEST,'mid') && ! $search) {
|
||||
$pinned = new \Zotlabs\Widget\Pinned;
|
||||
$r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]);
|
||||
$o .= $r['html'];
|
||||
}
|
||||
|
||||
$mode = (($search) ? 'search' : 'channel');
|
||||
|
||||
|
||||
@@ -35,13 +35,6 @@ class Cloud extends \Zotlabs\Web\Controller {
|
||||
if (argc() > 1)
|
||||
$which = argv(1);
|
||||
|
||||
|
||||
if (argc() < 2 && intval(get_config('system','cloud_disable_siteroot'))) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
construct_page();
|
||||
killme();
|
||||
}
|
||||
|
||||
$profile = 0;
|
||||
|
||||
if ($which)
|
||||
|
||||
@@ -283,6 +283,28 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
if(! intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','post_comments'))) {
|
||||
$oneway = true;
|
||||
}
|
||||
|
||||
$perminfo['connpermcount']=0;
|
||||
$perminfo['connperms']=t('Accepts').': ';
|
||||
if(intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','post_comments'))) {
|
||||
$perminfo['connpermcount']++;
|
||||
$perminfo['connperms'] .= t('Comments');
|
||||
}
|
||||
if(intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','send_stream'))) {
|
||||
$perminfo['connpermcount']++;
|
||||
$perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ;
|
||||
$perminfo['connperms'] .= t('Stream items');
|
||||
}
|
||||
if(intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','post_wall'))) {
|
||||
$perminfo['connpermcount']++;
|
||||
$perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ;
|
||||
$perminfo['connperms'] .= t('Wall posts');
|
||||
}
|
||||
|
||||
if ($perminfo['connpermcount'] == 0) {
|
||||
$perminfo['connperms'] .= t('Nothing');
|
||||
}
|
||||
|
||||
|
||||
foreach($status as $str) {
|
||||
if(!$str)
|
||||
@@ -322,7 +344,11 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
'ignore' => ((! $rr['abook_ignored']) ? t('Ignore') : false),
|
||||
'recent_label' => t('Recent activity'),
|
||||
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']) . '&name=' . $rr['xchan_name'],
|
||||
'oneway' => $oneway
|
||||
'oneway' => $oneway,
|
||||
'perminfo' => $perminfo,
|
||||
'connect' => (intval($rr['abook_not_here']) ? t('Connect') : ''),
|
||||
'follow' => z_root() . '/follow/?f=&url=' . urlencode($rr['xchan_hash']) . '&interactive=0',
|
||||
'connect_hover' => t('Connect at this location')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ class Dav extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
$auth = new \Zotlabs\Storage\BasicAuth();
|
||||
$auth->observer = get_observer_hash();
|
||||
|
||||
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV');
|
||||
|
||||
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
|
||||
|
||||
52
Zotlabs/Module/Dircensor.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
|
||||
class Dircensor extends Controller {
|
||||
|
||||
function get() {
|
||||
if(! is_site_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
|
||||
if (! ($dirmode == DIRECTORY_MODE_PRIMARY || $dirmode == DIRECTORY_MODE_STANDALONE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$xchan = argv(1);
|
||||
if(! $xchan) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
$val = (($r[0]['xchan_censored']) ? 0 : 1);
|
||||
|
||||
q("update xchan set xchan_censored = $val where xchan_hash = '%s'",
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if($val) {
|
||||
info( t('Entry censored') . EOL);
|
||||
}
|
||||
else {
|
||||
info( t('Entry uncensored') . EOL);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/directory');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,15 +2,19 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/dir_fns.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
|
||||
class Directory extends \Zotlabs\Web\Controller {
|
||||
class Directory extends Controller {
|
||||
|
||||
function init() {
|
||||
\App::set_pager_itemspage(60);
|
||||
App::set_pager_itemspage(60);
|
||||
|
||||
if(local_channel() && x($_GET,'ignore')) {
|
||||
q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
|
||||
@@ -21,7 +25,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if(local_channel())
|
||||
\App::$profile_uid = local_channel();
|
||||
App::$profile_uid = local_channel();
|
||||
|
||||
$observer = get_observer_hash();
|
||||
$global_changed = false;
|
||||
@@ -140,9 +144,15 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
|
||||
$directory_admin = false;
|
||||
|
||||
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
|
||||
$url = z_root() . '/dirsearch';
|
||||
}
|
||||
if (is_site_admin()) {
|
||||
$directory_admin = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(! $url) {
|
||||
$directory = find_upstream_directory($dirmode);
|
||||
if((! $directory) || (! array_key_exists('url',$directory)) || (! $directory['url']))
|
||||
@@ -182,7 +192,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
$query .= '&t=' . $token;
|
||||
|
||||
if(! $globaldir)
|
||||
$query .= '&hub=' . \App::get_hostname();
|
||||
$query .= '&hub=' . App::get_hostname();
|
||||
|
||||
if($search)
|
||||
$query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search);
|
||||
@@ -204,8 +214,8 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
if($sort_order)
|
||||
$query .= '&order=' . urlencode($sort_order);
|
||||
|
||||
if(\App::$pager['page'] != 1)
|
||||
$query .= '&p=' . \App::$pager['page'];
|
||||
if(App::$pager['page'] != 1)
|
||||
$query .= '&p=' . App::$pager['page'];
|
||||
|
||||
logger('mod_directory: query: ' . $query);
|
||||
|
||||
@@ -283,12 +293,15 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
$marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False);
|
||||
|
||||
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False);
|
||||
$homepageurl = ((x($profile,'homepage') == 1) ? $profile['homepage'] : '');
|
||||
$homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : '');
|
||||
|
||||
$hometown = ((x($profile,'hometown') == 1) ? $profile['hometown'] : False);
|
||||
|
||||
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'])) : False);
|
||||
$hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False);
|
||||
|
||||
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'], ['tryoembed' => false])) : False);
|
||||
if ($about && $safe_mode) {
|
||||
$about = html2plain($about);
|
||||
}
|
||||
|
||||
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
|
||||
|
||||
|
||||
@@ -343,9 +356,11 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
'canrate' => (($rating_enabled && local_channel()) ? true : false),
|
||||
'pdesc' => $pdesc,
|
||||
'pdesc_label' => t('Description:'),
|
||||
'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] : ''),
|
||||
'censor_label' => (($rr['censored']) ? t('Uncensor') : t('Censor')),
|
||||
'marital' => $marital,
|
||||
'homepage' => $homepage,
|
||||
'homepageurl' => linkify($homepageurl),
|
||||
'homepageurl' => (($safe_mode) ? $homepageurl : linkify($homepageurl)),
|
||||
'hometown' => $hometown,
|
||||
'hometown_label' => t('Hometown:'),
|
||||
'about' => $about,
|
||||
@@ -387,7 +402,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
ksort($entries); // Sort array by key so that foreach-constructs work as expected
|
||||
|
||||
if($j['keywords']) {
|
||||
\App::$data['directory_keywords'] = $j['keywords'];
|
||||
App::$data['directory_keywords'] = $j['keywords'];
|
||||
}
|
||||
|
||||
logger('mod_directory: entries: ' . print_r($entries,true), LOGGER_DATA);
|
||||
@@ -438,7 +453,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
echo $o;
|
||||
killme();
|
||||
}
|
||||
if(\App::$pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) {
|
||||
if(App::$pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) {
|
||||
goaway(z_root() . '/chanview/?f=&address=' . $search);
|
||||
}
|
||||
info( t("No entries (some entries may be hidden).") . EOL);
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/dir_fns.php');
|
||||
|
||||
|
||||
|
||||
class Dirsearch extends \Zotlabs\Web\Controller {
|
||||
class Dirsearch extends Controller {
|
||||
|
||||
function init() {
|
||||
\App::set_pager_itemspage(60);
|
||||
App::set_pager_itemspage(60);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +28,8 @@ class Dirsearch extends \Zotlabs\Web\Controller {
|
||||
$ret['message'] = t('This site is not a directory server');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$access_token = $_REQUEST['t'];
|
||||
|
||||
$token = get_config('system','realm_token');
|
||||
@@ -286,29 +290,29 @@ class Dirsearch extends \Zotlabs\Web\Controller {
|
||||
else
|
||||
$entry['total_ratings'] = 0;
|
||||
|
||||
$entry['name'] = $rr['xchan_name'];
|
||||
$entry['hash'] = $rr['xchan_hash'];
|
||||
|
||||
$entry['name'] = $rr['xchan_name'];
|
||||
$entry['hash'] = $rr['xchan_hash'];
|
||||
$entry['censored'] = $rr['xchan_censored'];
|
||||
$entry['selfcensored'] = $rr['xchan_selfcensored'];
|
||||
$entry['public_forum'] = (intval($rr['xchan_pubforum']) ? true : false);
|
||||
|
||||
$entry['url'] = $rr['xchan_url'];
|
||||
$entry['photo_l'] = $rr['xchan_photo_l'];
|
||||
$entry['photo'] = $rr['xchan_photo_m'];
|
||||
$entry['address'] = $rr['xchan_addr'];
|
||||
$entry['description'] = $rr['xprof_desc'];
|
||||
$entry['locale'] = $rr['xprof_locale'];
|
||||
$entry['region'] = $rr['xprof_region'];
|
||||
$entry['postcode'] = $rr['xprof_postcode'];
|
||||
$entry['country'] = $rr['xprof_country'];
|
||||
$entry['birthday'] = $rr['xprof_dob'];
|
||||
$entry['age'] = $rr['xprof_age'];
|
||||
$entry['gender'] = $rr['xprof_gender'];
|
||||
$entry['marital'] = $rr['xprof_marital'];
|
||||
$entry['sexual'] = $rr['xprof_sexual'];
|
||||
$entry['about'] = $rr['xprof_about'];
|
||||
$entry['homepage'] = $rr['xprof_homepage'];
|
||||
$entry['hometown'] = $rr['xprof_hometown'];
|
||||
$entry['keywords'] = $rr['xprof_keywords'];
|
||||
$entry['url'] = $rr['xchan_url'];
|
||||
$entry['photo_l'] = $rr['xchan_photo_l'];
|
||||
$entry['photo'] = $rr['xchan_photo_m'];
|
||||
$entry['address'] = $rr['xchan_addr'];
|
||||
$entry['description'] = $rr['xprof_desc'];
|
||||
$entry['locale'] = $rr['xprof_locale'];
|
||||
$entry['region'] = $rr['xprof_region'];
|
||||
$entry['postcode'] = $rr['xprof_postcode'];
|
||||
$entry['country'] = $rr['xprof_country'];
|
||||
$entry['birthday'] = $rr['xprof_dob'];
|
||||
$entry['age'] = $rr['xprof_age'];
|
||||
$entry['gender'] = $rr['xprof_gender'];
|
||||
$entry['marital'] = $rr['xprof_marital'];
|
||||
$entry['sexual'] = $rr['xprof_sexual'];
|
||||
$entry['about'] = $rr['xprof_about'];
|
||||
$entry['homepage'] = $rr['xprof_homepage'];
|
||||
$entry['hometown'] = $rr['xprof_hometown'];
|
||||
$entry['keywords'] = $rr['xprof_keywords'];
|
||||
|
||||
$entries[] = $entry;
|
||||
|
||||
|
||||
@@ -200,7 +200,8 @@ class Display 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['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($decoded)
|
||||
@@ -223,6 +224,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
'$conv' => '0',
|
||||
'$spam' => '0',
|
||||
'$fh' => '0',
|
||||
'$dm' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
|
||||
@@ -68,6 +68,8 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
||||
$ext = '.png';
|
||||
elseif($r[0]['mimetype'] === 'image/gif')
|
||||
$ext = '.gif';
|
||||
elseif($r[0]['mimetype'] === 'image/webp')
|
||||
$exp = '.webp';
|
||||
else
|
||||
$ext = EMPTY_STR;
|
||||
|
||||
|
||||
76
Zotlabs/Module/Event.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class Event extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(ActivityStreams::is_as_request()) {
|
||||
$item_id = argv(1);
|
||||
|
||||
if(! $item_id)
|
||||
return;
|
||||
|
||||
$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 ";
|
||||
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
|
||||
$r = q("select * from item where mid like '%s' $item_normal $sql_extra limit 1",
|
||||
dbesc(z_root() . '/activity/' . $item_id . '%')
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
$r = q("select * from item where mid like '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/activity/' . $item_id . '%')
|
||||
);
|
||||
|
||||
if($r) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
xchan_query($r,true);
|
||||
$items = fetch_post_tags($r,true);
|
||||
|
||||
$channel = channelx_by_n($items[0]['uid']);
|
||||
|
||||
if(! is_array($items[0]['obj'])) {
|
||||
$obj = json_decode($items[0]['obj'],true);
|
||||
}
|
||||
else {
|
||||
$obj = $items[0]['obj'];
|
||||
}
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], $obj );
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$channel);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
|
||||
HTTPSig::set_headers($h);
|
||||
|
||||
echo $ret;
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -66,7 +66,10 @@ class Help extends \Zotlabs\Web\Controller {
|
||||
case IMAGETYPE_PNG:
|
||||
header("Content-Type: image/png");
|
||||
break;
|
||||
default:
|
||||
case IMAGETYPE_WEBP:
|
||||
header("Content-Type: image/webp");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
header("Content-Length: " . filesize($realpath));
|
||||
|
||||
@@ -152,8 +152,8 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($target_item) {
|
||||
// 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['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($decoded)
|
||||
$mid = 'b64.' . base64url_encode($mid);
|
||||
@@ -179,6 +179,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
'$conv' => '0',
|
||||
'$spam' => '0',
|
||||
'$fh' => '0',
|
||||
'$dm' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
|
||||
@@ -42,8 +42,6 @@ class Item extends Controller {
|
||||
|
||||
if (Libzot::is_zot_request()) {
|
||||
|
||||
$conversation = false;
|
||||
|
||||
$item_id = argv(1);
|
||||
|
||||
if (! $item_id)
|
||||
@@ -273,7 +271,9 @@ class Item extends Controller {
|
||||
|
||||
$consensus = intval($_REQUEST['consensus']);
|
||||
$nocomment = intval($_REQUEST['nocomment']);
|
||||
|
||||
|
||||
$is_poll = ((trim($_REQUEST['poll_answers'][0]) != '' && trim($_REQUEST['poll_answers'][1]) != '') ? true : false);
|
||||
|
||||
// 'origin' (if non-zero) indicates that this network is where the message originated,
|
||||
// for the purpose of relaying comments to other conversation members.
|
||||
// If using the API from a device (leaf node) you must set origin to 1 (default) or leave unset.
|
||||
@@ -720,7 +720,6 @@ class Item extends Controller {
|
||||
// BBCODE alert: the following functions assume bbcode input
|
||||
// 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
|
||||
|
||||
|
||||
if(strpos($body,'[/summary]') !== false) {
|
||||
$match = '';
|
||||
@@ -817,11 +816,6 @@ class Item extends Controller {
|
||||
'revision' => $r['data']['revision']
|
||||
);
|
||||
}
|
||||
$ext = substr($r['data']['filename'],strrpos($r['data']['filename'],'.'));
|
||||
if(strpos($r['data']['filetype'],'audio/') !== false)
|
||||
$attach_link = '[audio]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . (($ext) ? $ext : '') . '[/audio]';
|
||||
elseif(strpos($r['data']['filetype'],'video/') !== false)
|
||||
$attach_link = '[video]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . (($ext) ? $ext : '') . '[/video]';
|
||||
$body = str_replace($match[1][$i],$attach_link,$body);
|
||||
$i++;
|
||||
}
|
||||
@@ -929,6 +923,27 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
|
||||
if($is_poll) {
|
||||
$poll = [
|
||||
'question' => $body,
|
||||
'answers' => $_REQUEST['poll_answers'],
|
||||
'multiple_answers' => $_REQUEST['poll_multiple_answers'],
|
||||
'expire_value' => $_REQUEST['poll_expire_value'],
|
||||
'expire_unit' => $_REQUEST['poll_expire_unit']
|
||||
];
|
||||
$obj = $this->extract_poll_data($poll, [ 'item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny ]);
|
||||
}
|
||||
else {
|
||||
$obj = $this->extract_bb_poll_data($body,[ 'item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny ]);
|
||||
}
|
||||
|
||||
if ($obj) {
|
||||
$obj['url'] = $mid;
|
||||
$obj['attributedTo'] = channel_url($channel);
|
||||
$datarray['obj'] = $obj;
|
||||
$obj_type = 'Question';
|
||||
}
|
||||
|
||||
if(! $parent_mid) {
|
||||
$parent_mid = $mid;
|
||||
}
|
||||
@@ -977,7 +992,11 @@ class Item extends Controller {
|
||||
$plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid);
|
||||
$plink = substr($plink,0,190);
|
||||
}
|
||||
|
||||
|
||||
if ($datarray['obj']) {
|
||||
$datarray['obj']['id'] = $mid;
|
||||
}
|
||||
|
||||
$datarray['aid'] = $channel['channel_account_id'];
|
||||
$datarray['uid'] = $profile_uid;
|
||||
$datarray['uuid'] = $uuid;
|
||||
@@ -1232,13 +1251,7 @@ class Item extends Controller {
|
||||
killme();
|
||||
}
|
||||
|
||||
if(($parent) && ($parent != $post_id)) {
|
||||
// Store the comment signature information in case we need to relay to Diaspora
|
||||
//$ditem = $datarray;
|
||||
//$ditem['author'] = $observer;
|
||||
//store_diaspora_comment_sig($ditem,$channel,$parent_item, $post_id, (($walltowall_comment) ? 1 : 0));
|
||||
}
|
||||
else {
|
||||
if(($parent == $post_id) || ($datarray['item_private'] == 1)) {
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($post_id)
|
||||
);
|
||||
@@ -1400,5 +1413,104 @@ class Item extends Controller {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
function extract_bb_poll_data(&$body,$item) {
|
||||
|
||||
$multiple = false;
|
||||
|
||||
if (strpos($body,'[/question]') === false && strpos($body,'[/answer]') === false) {
|
||||
return false;
|
||||
}
|
||||
if (strpos($body,'[nobb]') !== false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$obj = [];
|
||||
$ptr = [];
|
||||
$matches = null;
|
||||
$obj['type'] = 'Question';
|
||||
|
||||
if (preg_match_all('/\[answer\](.*?)\[\/answer\]/ism',$body,$matches,PREG_SET_ORDER)) {
|
||||
foreach ($matches as $match) {
|
||||
$ptr[] = [ 'name' => $match[1], 'type' => 'Note', 'replies' => [ 'type' => 'Collection', 'totalItems' => 0 ]];
|
||||
$body = str_replace('[answer]' . $match[1] . '[/answer]', EMPTY_STR, $body);
|
||||
}
|
||||
}
|
||||
|
||||
$matches = null;
|
||||
|
||||
if (preg_match('/\[question\](.*?)\[\/question\]/ism',$body,$matches)) {
|
||||
$obj['content'] = bbcode($matches[1]);
|
||||
$body = str_replace('[question]' . $matches[1] . '[/question]', $matches[1], $body);
|
||||
$obj['oneOf'] = $ptr;
|
||||
}
|
||||
|
||||
$matches = null;
|
||||
|
||||
if (preg_match('/\[question=multiple\](.*?)\[\/question\]/ism',$body,$matches)) {
|
||||
$obj['content'] = bbcode($matches[1]);
|
||||
$body = str_replace('[question=multiple]' . $matches[1] . '[/question]', $matches[1], $body);
|
||||
$obj['anyOf'] = $ptr;
|
||||
}
|
||||
|
||||
$matches = null;
|
||||
|
||||
if (preg_match('/\[ends\](.*?)\[\/ends\]/ism',$body,$matches)) {
|
||||
$obj['endTime'] = datetime_convert(date_default_timezone_get(),'UTC', $matches[1],ATOM_TIME);
|
||||
$body = str_replace('[ends]' . $matches[1] . '[/ends]', EMPTY_STR, $body);
|
||||
}
|
||||
|
||||
|
||||
if ($item['item_private']) {
|
||||
$obj['to'] = Activity::map_acl($item);
|
||||
}
|
||||
else {
|
||||
$obj['to'] = [ ACTIVITY_PUBLIC_INBOX ];
|
||||
}
|
||||
|
||||
return $obj;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function extract_poll_data($poll, $item) {
|
||||
|
||||
$multiple = intval($poll['multiple_answers']);
|
||||
$expire_value = intval($poll['expire_value']);
|
||||
$expire_unit = $poll['expire_unit'];
|
||||
$question = $poll['question'];
|
||||
$answers = $poll['answers'];
|
||||
|
||||
$obj = [];
|
||||
$ptr = [];
|
||||
$obj['type'] = 'Question';
|
||||
$obj['content'] = bbcode($question);
|
||||
|
||||
foreach($answers as $answer) {
|
||||
if(trim($answer))
|
||||
$ptr[] = [ 'name' => escape_tags($answer), 'type' => 'Note', 'replies' => [ 'type' => 'Collection', 'totalItems' => 0 ]];
|
||||
}
|
||||
|
||||
if($multiple) {
|
||||
$obj['anyOf'] = $ptr;
|
||||
}
|
||||
else {
|
||||
$obj['oneOf'] = $ptr;
|
||||
}
|
||||
|
||||
$obj['endTime'] = datetime_convert(date_default_timezone_get(), 'UTC', 'now + ' . $expire_value . ' ' . $expire_unit, ATOM_TIME);
|
||||
|
||||
if ($item['item_private']) {
|
||||
$obj['to'] = Activity::map_acl($item);
|
||||
}
|
||||
else {
|
||||
$obj['to'] = [ ACTIVITY_PUBLIC_INBOX ];
|
||||
}
|
||||
|
||||
return $obj;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -75,7 +75,12 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
|
||||
$is_rsvp = false;
|
||||
if (in_array($activity, [ ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE ])) {
|
||||
$is_rsvp = true;
|
||||
}
|
||||
|
||||
|
||||
$extended_like = false;
|
||||
$object = $target = null;
|
||||
$post_type = EMPTY_STR;
|
||||
@@ -381,7 +386,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$arr = array();
|
||||
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = z_root() . '/item/' . $uuid;
|
||||
$arr['mid'] = z_root() . (($is_rsvp) ? '/activity/' : '/item/') . $uuid;
|
||||
|
||||
if($extended_like) {
|
||||
$arr['item_thread_top'] = 1;
|
||||
|
||||
@@ -1,449 +0,0 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/message.php');
|
||||
require_once('include/zot.php');
|
||||
require_once("include/bbcode.php");
|
||||
|
||||
|
||||
|
||||
|
||||
class Mail extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
$replyto = ((x($_REQUEST,'replyto')) ? notags(trim($_REQUEST['replyto'])) : '');
|
||||
$subject = ((x($_REQUEST,'subject')) ? notags(trim($_REQUEST['subject'])) : '');
|
||||
$body = ((x($_REQUEST,'body')) ? escape_tags(trim($_REQUEST['body'])) : '');
|
||||
$recipient = ((x($_REQUEST,'messageto')) ? notags(trim(urldecode($_REQUEST['messageto']))) : '');
|
||||
$rstr = ((x($_REQUEST,'messagerecip')) ? notags(trim($_REQUEST['messagerecip'])) : '');
|
||||
$preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0);
|
||||
$expires = ((x($_REQUEST,'expires')) ? datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expires']) : NULL_DATE);
|
||||
$raw = ((x($_REQUEST,'raw')) ? intval($_REQUEST['raw']) : 0);
|
||||
$mimetype = ((x($_REQUEST,'mimetype')) ? notags(trim($_REQUEST['mimetype'])) : 'text/bbcode');
|
||||
|
||||
$sig = ((x($_REQUEST,'signature')) ? trim($_REQUEST['signature']) : '');
|
||||
if(strpos($sig,'b64.') === 0)
|
||||
$sig = base64_decode(str_replace('b64.', '', $sig));
|
||||
|
||||
if($preview) {
|
||||
|
||||
if($raw) {
|
||||
$body = mail_prepare_binary(['id' => 'M0']);
|
||||
echo json_encode(['preview' => $body]);
|
||||
}
|
||||
else {
|
||||
$body = cleanup_bbcode($body);
|
||||
$results = linkify_tags($body, local_channel());
|
||||
|
||||
if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
|
||||
$attachments = array();
|
||||
foreach($match[2] as $mtch) {
|
||||
$hash = substr($mtch,0,strpos($mtch,','));
|
||||
$rev = intval(substr($mtch,strpos($mtch,',')));
|
||||
$r = attach_by_hash_nodata($hash,get_observer_hash(),$rev);
|
||||
if($r['success']) {
|
||||
$attachments[] = array(
|
||||
'href' => z_root() . '/attach/' . $r['data']['hash'],
|
||||
'length' => $r['data']['filesize'],
|
||||
'type' => $r['data']['filetype'],
|
||||
'title' => urlencode($r['data']['filename']),
|
||||
'revision' => $r['data']['revision']
|
||||
);
|
||||
}
|
||||
$body = trim(str_replace($match[1],'',$body));
|
||||
}
|
||||
}
|
||||
echo json_encode(['preview' => zidify_links(smilies(bbcode($body)))]);
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
// If we have a raw string for a recipient which hasn't been auto-filled,
|
||||
// it means they probably aren't in our address book, hence we don't know
|
||||
// if we have permission to send them private messages.
|
||||
// finger them and find out before we try and send it.
|
||||
|
||||
if(! $recipient) {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$j = \Zotlabs\Zot\Finger::run(punify($rstr),$channel);
|
||||
|
||||
if(! $j['success']) {
|
||||
notice( t('Unable to lookup recipient.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
logger('message_post: lookup: ' . $rstr . ' ' . print_r($j,true));
|
||||
|
||||
if(! $j['guid']) {
|
||||
notice( t('Unable to communicate with requested channel.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$x = import_xchan($j);
|
||||
|
||||
if(! $x['success']) {
|
||||
notice( t('Cannot verify requested channel.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$recipient = $x['hash'];
|
||||
|
||||
$their_perms = 0;
|
||||
|
||||
if($j['permissions']['data']) {
|
||||
$permissions = crypto_unencapsulate($j['permissions'],$channel['channel_prvkey']);
|
||||
if($permissions)
|
||||
$permissions = json_decode($permissions, true);
|
||||
logger('decrypted permissions: ' . print_r($permissions,true), LOGGER_DATA);
|
||||
}
|
||||
else
|
||||
$permissions = $j['permissions'];
|
||||
|
||||
if(! ($permissions['post_mail'])) {
|
||||
notice( t('Selected channel has private message restrictions. Send failed.'));
|
||||
// reported issue: let's still save the message and continue. We'll just tell them
|
||||
// that nothing useful is likely to happen. They might have spent hours on it.
|
||||
// return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
require_once('include/text.php');
|
||||
linkify_tags($body, local_channel());
|
||||
|
||||
|
||||
if(! $recipient) {
|
||||
notice('No recipient found.');
|
||||
\App::$argc = 2;
|
||||
\App::$argv[1] = 'new';
|
||||
return;
|
||||
}
|
||||
|
||||
// We have a local_channel, let send_message use the session channel and save a lookup
|
||||
|
||||
$ret = send_message(0, $recipient, $body, $subject, $replyto, $expires, $mimetype, $raw, $sig);
|
||||
|
||||
if($ret['success']) {
|
||||
xchan_mail_query($ret['mail']);
|
||||
build_sync_packet(0,array('conv' => array($ret['conv']),'mail' => array(encode_mail($ret['mail'],true))));
|
||||
}
|
||||
else {
|
||||
notice($ret['message']);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/mail/combined');
|
||||
|
||||
}
|
||||
|
||||
function get() {
|
||||
|
||||
$o = '';
|
||||
nav_set_selected('Mail');
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return login();
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
head_set_icon($channel['xchan_photo_s']);
|
||||
|
||||
$cipher = get_pconfig(local_channel(),'system','default_cipher');
|
||||
if(! $cipher)
|
||||
$cipher = 'aes256';
|
||||
|
||||
$tpl = get_markup_template('mail_head.tpl');
|
||||
$header = replace_macros($tpl, array(
|
||||
'$header' => t('Messages'),
|
||||
));
|
||||
|
||||
if(argc() == 3 && intval(argv(1)) && argv(2) === 'download') {
|
||||
|
||||
$r = q("select * from mail where id = %d and channel_id = %d",
|
||||
intval(argv(1)),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($r) {
|
||||
|
||||
header('Content-type: ' . $r[0]['mail_mimetype']);
|
||||
header('Content-disposition: attachment; filename="' . t('message') . '-' . $r[0]['id'] . '"' );
|
||||
$body = (($r[0]['mail_obscured']) ? base64url_decode(str_rot47($r[0]['body'])) : $r[0]['body']);
|
||||
echo $body;
|
||||
killme();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if((argc() == 4) && (argv(2) === 'drop')) {
|
||||
if(! intval(argv(3)))
|
||||
return;
|
||||
$cmd = argv(2);
|
||||
$mailbox = argv(1);
|
||||
$r = private_messages_drop(local_channel(), argv(3));
|
||||
if($r) {
|
||||
//info( t('Message deleted.') . EOL );
|
||||
}
|
||||
goaway(z_root() . '/mail/' . $mailbox);
|
||||
}
|
||||
|
||||
if((argc() == 4) && (argv(2) === 'recall')) {
|
||||
if(! intval(argv(3)))
|
||||
return;
|
||||
$cmd = argv(2);
|
||||
$mailbox = argv(1);
|
||||
$r = q("update mail set mail_recalled = 1 where id = %d and channel_id = %d",
|
||||
intval(argv(3)),
|
||||
intval(local_channel())
|
||||
);
|
||||
$x = q("select * from mail where id = %d and channel_id = %d",
|
||||
intval(argv(3)),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($x) {
|
||||
build_sync_packet(local_channel(),array('mail' => encode_mail($x[0],true)));
|
||||
}
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','mail',intval(argv(3))));
|
||||
|
||||
if($r) {
|
||||
info( t('Message recalled.') . EOL );
|
||||
}
|
||||
goaway(z_root() . '/mail/' . $mailbox . '/' . argv(3));
|
||||
|
||||
}
|
||||
|
||||
if((argc() == 4) && (argv(2) === 'dropconv')) {
|
||||
if(! intval(argv(3)))
|
||||
return;
|
||||
$cmd = argv(2);
|
||||
$mailbox = argv(1);
|
||||
$r = private_messages_drop(local_channel(), argv(3), true);
|
||||
if($r)
|
||||
info( t('Conversation removed.') . EOL );
|
||||
goaway(z_root() . '/mail/' . $mailbox);
|
||||
}
|
||||
|
||||
if((argc() > 1) && (argv(1) === 'new')) {
|
||||
|
||||
$plaintext = true;
|
||||
|
||||
$tpl = get_markup_template('msg-header.tpl');
|
||||
|
||||
$header = replace_macros($tpl, array(
|
||||
'$baseurl' => z_root(),
|
||||
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
|
||||
'$nickname' => $channel['channel_address'],
|
||||
'$linkurl' => t('Please enter a link URL:'),
|
||||
'$expireswhen' => t('Expires YYYY-MM-DD HH:MM')
|
||||
));
|
||||
|
||||
\App::$page['htmlhead'] .= $header;
|
||||
|
||||
$prename = '';
|
||||
$preid = '';
|
||||
|
||||
if(x($_REQUEST,'hash')) {
|
||||
|
||||
$r = q("select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash
|
||||
where abook_channel = %d and abook_xchan = '%s' limit 1",
|
||||
intval(local_channel()),
|
||||
dbesc($_REQUEST['hash'])
|
||||
);
|
||||
|
||||
if(!$r) {
|
||||
$r = q("select * from xchan where xchan_hash = '%s' and xchan_network = 'zot' limit 1",
|
||||
dbesc($_REQUEST['hash'])
|
||||
);
|
||||
}
|
||||
|
||||
if($r) {
|
||||
$prename = (($r[0]['abook_id']) ? $r[0]['xchan_name'] : $r[0]['xchan_addr']);
|
||||
$preurl = $r[0]['xchan_url'];
|
||||
$preid = (($r[0]['abook_id']) ? ($r[0]['xchan_hash']) : '');
|
||||
}
|
||||
else {
|
||||
notice( t('Requested channel is not in this network') . EOL );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$tpl = get_markup_template('prv_message.tpl');
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$new' => true,
|
||||
'$header' => t('Send Private Message'),
|
||||
'$to' => t('To:'),
|
||||
'$prefill' => $prename,
|
||||
'$preid' => $preid,
|
||||
'$subject' => t('Subject:'),
|
||||
'$subjtxt' => ((x($_REQUEST,'subject')) ? strip_tags($_REQUEST['subject']) : ''),
|
||||
'$text' => ((x($_REQUEST,'body')) ? htmlspecialchars($_REQUEST['body'], ENT_COMPAT, 'UTF-8') : ''),
|
||||
'$yourmessage' => t('Your message:'),
|
||||
'$parent' => '',
|
||||
'$attach' => t('Attach file'),
|
||||
'$insert' => t('Insert web link'),
|
||||
'$submit' => t('Send'),
|
||||
'$defexpire' => '',
|
||||
'$feature_expire' => ((feature_enabled(local_channel(),'content_expire')) ? true : false),
|
||||
'$expires' => t('Set expiration date'),
|
||||
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
|
||||
'$encrypt' => t('Encrypt text'),
|
||||
'$cipher' => $cipher,
|
||||
));
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
$direct_mid = 0;
|
||||
|
||||
switch(argv(1)) {
|
||||
case 'combined':
|
||||
$mailbox = 'combined';
|
||||
break;
|
||||
case 'inbox':
|
||||
$mailbox = 'inbox';
|
||||
break;
|
||||
case 'outbox':
|
||||
$mailbox = 'outbox';
|
||||
break;
|
||||
default:
|
||||
$mailbox = 'combined';
|
||||
|
||||
// notifications direct to mail/nn
|
||||
|
||||
if(intval(argv(1)))
|
||||
$direct_mid = intval(argv(1));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$last_message = private_messages_list(local_channel(), $mailbox, 0, 1);
|
||||
|
||||
$mid = ((argc() > 2) && (intval(argv(2)))) ? argv(2) : $last_message[0]['id'];
|
||||
|
||||
if($direct_mid)
|
||||
$mid = $direct_mid;
|
||||
|
||||
|
||||
$plaintext = true;
|
||||
|
||||
// if( local_channel() && feature_enabled(local_channel(),'richtext') )
|
||||
// $plaintext = false;
|
||||
|
||||
|
||||
|
||||
if($mailbox == 'combined') {
|
||||
$messages = private_messages_fetch_conversation(local_channel(), $mid, true);
|
||||
}
|
||||
else {
|
||||
$messages = private_messages_fetch_message(local_channel(), $mid, true);
|
||||
}
|
||||
|
||||
if(! $messages) {
|
||||
//info( t('Message not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if($messages[0]['to_xchan'] === $channel['channel_hash'])
|
||||
\App::$poi = $messages[0]['from'];
|
||||
else
|
||||
\App::$poi = $messages[0]['to'];
|
||||
|
||||
$tpl = get_markup_template('msg-header.tpl');
|
||||
|
||||
\App::$page['htmlhead'] .= replace_macros($tpl, array(
|
||||
'$nickname' => $channel['channel_address'],
|
||||
'$baseurl' => z_root(),
|
||||
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
|
||||
'$linkurl' => t('Please enter a link URL:'),
|
||||
'$expireswhen' => t('Expires YYYY-MM-DD HH:MM')
|
||||
));
|
||||
|
||||
$mails = array();
|
||||
|
||||
$seen = 0;
|
||||
$unknown = false;
|
||||
|
||||
foreach($messages as $message) {
|
||||
|
||||
$s = theme_attachments($message);
|
||||
|
||||
if($message['mail_raw'])
|
||||
$message['body'] = mail_prepare_binary([ 'id' => $message['id'] ]);
|
||||
else
|
||||
$message['body'] = zidify_links(smilies(bbcode($message['body'])));
|
||||
|
||||
$mails[] = array(
|
||||
'mailbox' => $mailbox,
|
||||
'id' => $message['id'],
|
||||
'mid' => $message['mid'],
|
||||
'from_name' => $message['from']['xchan_name'],
|
||||
'from_url' => chanlink_hash($message['from_xchan']),
|
||||
'from_photo' => $message['from']['xchan_photo_s'],
|
||||
'to_name' => $message['to']['xchan_name'],
|
||||
'to_url' => chanlink_hash($message['to_xchan']),
|
||||
'to_photo' => $message['to']['xchan_photo_s'],
|
||||
'subject' => $message['title'],
|
||||
'body' => $message['body'],
|
||||
'attachments' => $s,
|
||||
'delete' => t('Delete message'),
|
||||
'dreport' => t('Delivery report'),
|
||||
'recall' => t('Recall message'),
|
||||
'can_recall' => ($channel['channel_hash'] == $message['from_xchan']),
|
||||
'is_recalled' => (intval($message['mail_recalled']) ? t('Message has been recalled.') : ''),
|
||||
'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c'),
|
||||
'sig' => base64_encode($message['sig'])
|
||||
);
|
||||
|
||||
$seen = $message['seen'];
|
||||
|
||||
}
|
||||
|
||||
$recp = (($message['from_xchan'] === $channel['channel_hash']) ? 'to' : 'from');
|
||||
|
||||
$tpl = get_markup_template('mail_display.tpl');
|
||||
$o = replace_macros($tpl, array(
|
||||
'$mailbox' => $mailbox,
|
||||
'$prvmsg_header' => $message['title'],
|
||||
'$thread_id' => $mid,
|
||||
'$thread_subject' => $message['title'],
|
||||
'$thread_seen' => $seen,
|
||||
'$delete' => t('Delete Conversation'),
|
||||
'$canreply' => (($unknown) ? false : '1'),
|
||||
'$unknown_text' => t("No secure communications available. You <strong>may</strong> be able to respond from the sender's profile page."),
|
||||
'$mails' => $mails,
|
||||
|
||||
// reply
|
||||
'$header' => t('Send Reply'),
|
||||
'$to' => t('To:'),
|
||||
'$reply' => true,
|
||||
'$subject' => t('Subject:'),
|
||||
'$subjtxt' => $message['title'],
|
||||
'$yourmessage' => sprintf(t('Your message for %s (%s):'), $message[$recp]['xchan_name'], $message[$recp]['xchan_addr']),
|
||||
'$text' => '',
|
||||
'$parent' => $message['parent_mid'],
|
||||
'$recphash' => $message[$recp]['xchan_hash'],
|
||||
'$attach' => t('Attach file'),
|
||||
'$insert' => t('Insert web link'),
|
||||
'$submit' => t('Submit'),
|
||||
'$defexpire' => '',
|
||||
'$feature_expire' => ((feature_enabled(local_channel(),'content_expire')) ? true : false),
|
||||
'$expires' => t('Set expiration date'),
|
||||
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
|
||||
'$encrypt' => t('Encrypt text'),
|
||||
'$cipher' => $cipher,
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -54,9 +54,10 @@ class Menu extends \Zotlabs\Web\Controller {
|
||||
if($_REQUEST['menu_system'])
|
||||
$_REQUEST['menu_flags'] |= MENU_SYSTEM;
|
||||
|
||||
$menu_id = ((argc() > 1) ? intval(argv(1)) : 0);
|
||||
$menu_id = ((argc() > 2) ? intval(argv(2)) : 0);
|
||||
|
||||
if($menu_id) {
|
||||
$_REQUEST['menu_id'] = intval(argv(1));
|
||||
$_REQUEST['menu_id'] = $menu_id;
|
||||
$r = menu_edit($_REQUEST);
|
||||
if($r) {
|
||||
menu_sync_packet($uid,get_observer_hash(),$menu_id);
|
||||
|
||||
@@ -69,6 +69,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
|
||||
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
|
||||
$verb = ((x($_REQUEST,'verb')) ? $_REQUEST['verb'] : '');
|
||||
$dm = ((x($_REQUEST,'dm')) ? $_REQUEST['dm'] : 0);
|
||||
|
||||
|
||||
$order = get_pconfig(local_channel(), 'mod_network', 'order', 0);
|
||||
@@ -339,7 +340,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
// The special div is needed for liveUpdate to kick in for this page.
|
||||
// We only launch liveUpdate if you aren't filtering in some incompatible
|
||||
// way and also you aren't writing a comment (discovered in javascript).
|
||||
|
||||
|
||||
$maxheight = get_pconfig(local_channel(),'system','network_divmore_height');
|
||||
if(! $maxheight)
|
||||
$maxheight = 400;
|
||||
@@ -363,6 +364,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
'$conv' => (($conv) ? $conv : '0'),
|
||||
'$spam' => (($spam) ? $spam : '0'),
|
||||
'$fh' => '0',
|
||||
'$dm' => (($dm) ? $dm : '0'),
|
||||
'$nouveau' => (($nouveau) ? $nouveau : '0'),
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
@@ -409,15 +411,33 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if($verb) {
|
||||
$sql_extra .= sprintf(" AND item.verb like '%s' ",
|
||||
dbesc(protect_sprintf('%' . $verb . '%'))
|
||||
);
|
||||
if ($verb) {
|
||||
|
||||
// the presence of a leading dot in the verb determines
|
||||
// whether to match the type of activity or the child object.
|
||||
// The name 'verb' is a holdover from the earlier XML
|
||||
// ActivityStreams specification.
|
||||
|
||||
if (substr($verb,0,1) === '.') {
|
||||
$verb = substr($verb,1);
|
||||
$sql_extra .= sprintf(" AND item.obj_type like '%s' ",
|
||||
dbesc(protect_sprintf('%' . $verb . '%'))
|
||||
);
|
||||
}
|
||||
else {
|
||||
$sql_extra .= sprintf(" AND item.verb like '%s' ",
|
||||
dbesc(protect_sprintf('%' . $verb . '%'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen($file)) {
|
||||
$sql_extra .= term_query('item',$file,TERM_FILE);
|
||||
}
|
||||
|
||||
if ($dm) {
|
||||
$sql_extra .= " AND item_private = 2 ";
|
||||
}
|
||||
|
||||
if($conv) {
|
||||
$item_thread_top = '';
|
||||
|
||||
@@ -31,12 +31,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
// NOTREACHED
|
||||
}
|
||||
|
||||
$cache_mode = array(
|
||||
'on' => false,
|
||||
'age' => 86400,
|
||||
'exp' => true,
|
||||
'leak' => false
|
||||
);
|
||||
$cache_mode = [ 'on' => false, 'age' => 86400, 'exp' => true, 'leak' => false ];
|
||||
call_hooks('cache_mode_hook', $cache_mode);
|
||||
|
||||
$observer_xchan = get_observer_hash();
|
||||
@@ -144,7 +139,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
$resolution = 1;
|
||||
}
|
||||
|
||||
$r = q("SELECT uid, photo_usage, display_path FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
|
||||
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
|
||||
dbesc($photo),
|
||||
intval($resolution)
|
||||
);
|
||||
@@ -163,13 +158,10 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
if($u === PHOTO_CACHE) {
|
||||
// Validate cache
|
||||
if($cache_mode['on']) {
|
||||
$cache = array(
|
||||
'resid' => $photo,
|
||||
'status' => false
|
||||
);
|
||||
$cache = [ 'status' => false, 'item' => $r[0] ];
|
||||
call_hooks('cache_url_hook', $cache);
|
||||
if(! $cache['status']) {
|
||||
$url = html_entity_decode($r[0]['display_path'], ENT_QUOTES);
|
||||
$url = html_entity_decode($cache['item']['display_path'], ENT_QUOTES);
|
||||
// SSLify if needed
|
||||
if(strpos(z_root(),'https:') !== false && strpos($url,'https:') === false)
|
||||
$url = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($url);
|
||||
@@ -229,7 +221,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
header_remove('Pragma');
|
||||
|
||||
if($_SERVER['HTTP_IF_NONE_MATCH'] === $etag || $_SERVER['HTTP_IF_MODIFIED_SINCE'] === gmdate("D, d M Y H:i:s", $modified) . " GMT") {
|
||||
if((isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etag) || (!isset($_SERVER['HTTP_IF_NONE_MATCH']) && isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $_SERVER['HTTP_IF_MODIFIED_SINCE'] === gmdate("D, d M Y H:i:s", $modified) . " GMT")) {
|
||||
header_remove('Expires');
|
||||
header_remove('Cache-Control');
|
||||
header_remove('Set-Cookie');
|
||||
@@ -272,7 +264,12 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
$maxage = $expires - time();
|
||||
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT");
|
||||
header("Cache-Control: max-age=" . $maxage . $cachecontrol);
|
||||
|
||||
// set CDN/Infrastructure caching much lower than maxage
|
||||
// in the event that infrastructure caching is present.
|
||||
$smaxage = intval($maxage/12);
|
||||
|
||||
header("Cache-Control: s-maxage=" . $smaxage . ", max-age=" . $maxage . $cachecontrol);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1080,7 +1080,6 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
$comments = '';
|
||||
if(! $r) {
|
||||
if($observer && ($can_post || $can_comment)) {
|
||||
$feature_auto_save_draft = ((feature_enabled($owner_uid, 'auto_save_draft')) ? "true" : "false");
|
||||
$commentbox = replace_macros($cmnt_tpl,array(
|
||||
'$return_path' => '',
|
||||
'$mode' => 'photos',
|
||||
@@ -1096,8 +1095,7 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
'$submit' => t('Submit'),
|
||||
'$preview' => t('Preview'),
|
||||
'$ww' => '',
|
||||
'$feature_encrypt' => false,
|
||||
'$auto_save_draft' => $feature_auto_save_draft
|
||||
'$feature_encrypt' => false
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
69
Zotlabs/Module/Pin.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
/*
|
||||
* Pinned post processing
|
||||
*/
|
||||
|
||||
use App;
|
||||
|
||||
class Pin extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
function init() {
|
||||
|
||||
if(argc() !== 2)
|
||||
http_status_exit(400, 'Bad request');
|
||||
}
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
$item_id = intval($_POST['id']);
|
||||
|
||||
if ($item_id <= 0)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$observer = \App::get_observer();
|
||||
if(! $observer)
|
||||
http_status_exit(403, 'Forbidden');
|
||||
|
||||
$r = q("SELECT * FROM item WHERE id = %d AND id = parent AND item_private = 0 LIMIT 1",
|
||||
$item_id
|
||||
);
|
||||
if(! $r) {
|
||||
notice(t('Unable to locate original post.'));
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$midb64 = 'b64.' . base64url_encode($r[0]['mid']);
|
||||
$pinned = (in_array($midb64, get_pconfig($r[0]['uid'], 'pinned', $r[0]['item_type'], [])) ? true : false);
|
||||
|
||||
switch(argv(1)) {
|
||||
|
||||
case 'pin':
|
||||
if(! local_channel() || (local_channel() != $r[0]['uid'] && local_channel() != is_site_admin()))
|
||||
http_status_exit(403, 'Forbidden');
|
||||
// Currently allow only one pinned item for each type
|
||||
set_pconfig($r[0]['uid'], 'pinned', $r[0]['item_type'], ($pinned ? [] : [ $midb64 ]));
|
||||
if($pinned)
|
||||
del_pconfig($r[0]['uid'], 'pinned_hide', $midb64);
|
||||
break;
|
||||
|
||||
case 'hide':
|
||||
if($pinned) {
|
||||
$hidden = get_pconfig($r[0]['uid'], 'pinned_hide', $midb64, []);
|
||||
if(! in_array($observer['xchan_hash'], $hidden)) {
|
||||
$hidden[] = $observer['xchan_hash'];
|
||||
set_pconfig($r[0]['uid'], 'pinned_hide', $midb64, $hidden);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
build_sync_packet($r[0]['uid'], [ 'config' ]);
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,11 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
$net = ((array_key_exists('net',$_REQUEST)) ? escape_tags($_REQUEST['net']) : '');
|
||||
|
||||
$title = replace_macros(get_markup_template("section_title.tpl"),array(
|
||||
'$title' => (($hashtags) ? '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8') : '')
|
||||
));
|
||||
|
||||
$o = (($hashtags) ? $title : '');
|
||||
|
||||
if(local_channel() && (! $update)) {
|
||||
|
||||
@@ -94,7 +99,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
'reset' => t('Reset form')
|
||||
);
|
||||
|
||||
$o = '<div id="jot-popup">';
|
||||
$o .= '<div id="jot-popup">';
|
||||
$o .= status_editor($a,$x,false,'Pubstream');
|
||||
$o .= '</div>';
|
||||
}
|
||||
@@ -139,6 +144,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
'$conv' => '0',
|
||||
'$spam' => '0',
|
||||
'$fh' => '1',
|
||||
'$dm' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$list' => '0',
|
||||
@@ -285,7 +291,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
// fake it
|
||||
$mode = ('pubstream');
|
||||
$mode = (($hashtags) ? 'search' : 'pubstream');
|
||||
|
||||
$o .= conversation($items,$mode,$update,$page_mode);
|
||||
|
||||
|
||||
@@ -128,6 +128,7 @@ class Search extends \Zotlabs\Web\Controller {
|
||||
'$conv' => '0',
|
||||
'$spam' => '0',
|
||||
'$fh' => '0',
|
||||
'$dm' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
|
||||
121
Zotlabs/Module/Sse.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Enotify;
|
||||
use Zotlabs\Lib\XConfig;
|
||||
|
||||
class Sse extends Controller {
|
||||
|
||||
public static $uid;
|
||||
public static $ob_hash;
|
||||
public static $sse_id;
|
||||
public static $vnotify;
|
||||
|
||||
function init() {
|
||||
|
||||
if((observer_prohibited(true))) {
|
||||
killme();
|
||||
}
|
||||
|
||||
if(! intval(get_config('system','open_pubstream',1))) {
|
||||
if(! get_observer_hash()) {
|
||||
killme();
|
||||
}
|
||||
}
|
||||
|
||||
// this is important!
|
||||
session_write_close();
|
||||
|
||||
self::$uid = local_channel();
|
||||
self::$ob_hash = get_observer_hash();
|
||||
self::$sse_id = false;
|
||||
|
||||
if(! self::$ob_hash) {
|
||||
if(session_id()) {
|
||||
self::$sse_id = true;
|
||||
self::$ob_hash = 'sse_id.' . session_id();
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify');
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$sleep_seconds = 3;
|
||||
|
||||
header("Content-Type: text/event-stream");
|
||||
header("Cache-Control: no-cache");
|
||||
header("Connection: keep-alive");
|
||||
header("X-Accel-Buffering: no");
|
||||
|
||||
while(true) {
|
||||
|
||||
/**
|
||||
* Update chat presence indication (if applicable)
|
||||
*/
|
||||
|
||||
if(! self::$sse_id) {
|
||||
$r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
|
||||
dbesc(self::$ob_hash),
|
||||
dbesc($_SERVER['REMOTE_ADDR'])
|
||||
);
|
||||
$basic_presence = false;
|
||||
if($r) {
|
||||
$basic_presence = true;
|
||||
q("update chatpresence set cp_last = '%s' where cp_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['cp_id'])
|
||||
);
|
||||
}
|
||||
if(! $basic_presence) {
|
||||
q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
|
||||
values( '%s', '%s', '%s', '%s' ) ",
|
||||
dbesc(self::$ob_hash),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc('online'),
|
||||
dbesc($_SERVER['REMOTE_ADDR'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
XConfig::Load(self::$ob_hash);
|
||||
|
||||
$result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
|
||||
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
|
||||
|
||||
if($result && !$lock) {
|
||||
echo "event: notifications\n";
|
||||
echo 'data: ' . json_encode($result);
|
||||
echo "\n\n";
|
||||
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
|
||||
unset($result);
|
||||
}
|
||||
|
||||
// always send heartbeat to detect disconnected clients
|
||||
echo "event: heartbeat\n";
|
||||
echo 'data: {}';
|
||||
echo "\n\n";
|
||||
|
||||
ob_end_flush();
|
||||
flush();
|
||||
|
||||
if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
|
||||
//TODO: this does not seem to be triggered
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
|
||||
break;
|
||||
}
|
||||
|
||||
sleep($sleep_seconds);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
550
Zotlabs/Module/Sse_bs.php
Normal file
@@ -0,0 +1,550 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Enotify;
|
||||
|
||||
class Sse_bs extends Controller {
|
||||
|
||||
public static $uid;
|
||||
public static $ob_hash;
|
||||
public static $sse_id;
|
||||
public static $vnotify;
|
||||
public static $evdays;
|
||||
public static $limit;
|
||||
public static $offset;
|
||||
public static $xchans;
|
||||
|
||||
function init() {
|
||||
|
||||
self::$uid = local_channel();
|
||||
self::$ob_hash = get_observer_hash();
|
||||
self::$sse_id = false;
|
||||
|
||||
if(! self::$ob_hash) {
|
||||
if(session_id()) {
|
||||
self::$sse_id = true;
|
||||
self::$ob_hash = 'sse_id.' . session_id();
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify');
|
||||
self::$evdays = intval(get_pconfig(self::$uid, 'system', 'evdays'));
|
||||
self::$limit = 100;
|
||||
self::$offset = 0;
|
||||
self::$xchans = '';
|
||||
|
||||
if(!empty($_GET['nquery']) && $_GET['nquery'] !== '%') {
|
||||
$nquery = $_GET['nquery'];
|
||||
|
||||
$x = q("SELECT xchan_hash FROM xchan WHERE xchan_name LIKE '%s' OR xchan_addr LIKE '%s'",
|
||||
dbesc($nquery . '%'),
|
||||
dbesc($nquery . '%')
|
||||
);
|
||||
|
||||
self::$xchans = ids_to_querystr($x, 'xchan_hash', true);
|
||||
}
|
||||
|
||||
if(intval(argv(2)) > 0)
|
||||
self::$offset = argv(2);
|
||||
else
|
||||
$_SESSION['sse_loadtime'] = datetime_convert();
|
||||
|
||||
$network = false;
|
||||
$home = false;
|
||||
$pubs = false;
|
||||
$f = '';
|
||||
|
||||
switch (argv(1)) {
|
||||
case 'network':
|
||||
$network = true;
|
||||
$f = 'bs_network';
|
||||
break;
|
||||
case 'home':
|
||||
$home = true;
|
||||
$f = 'bs_home';
|
||||
break;
|
||||
case 'pubs':
|
||||
$pubs = true;
|
||||
$f = 'bs_pubs';
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
if(self::$offset && $f) {
|
||||
$result = self::$f(true);
|
||||
json_return_and_die($result);
|
||||
}
|
||||
|
||||
$result = array_merge(
|
||||
self::bs_network($network),
|
||||
self::bs_home($home),
|
||||
self::bs_notify(),
|
||||
self::bs_intros(),
|
||||
self::bs_forums(),
|
||||
self::bs_pubs($pubs),
|
||||
self::bs_files(),
|
||||
self::bs_mail(),
|
||||
self::bs_all_events(),
|
||||
self::bs_register()
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
json_return_and_die($result);
|
||||
}
|
||||
|
||||
function bs_network($notifications) {
|
||||
|
||||
$result['network']['notifications'] = [];
|
||||
$result['network']['count'] = 0;
|
||||
|
||||
if(! self::$uid)
|
||||
return $result;
|
||||
|
||||
$limit = intval(self::$limit);
|
||||
$offset = self::$offset;
|
||||
|
||||
$sql_extra = '';
|
||||
if(! (self::$vnotify & VNOTIFY_LIKE))
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
|
||||
$sql_extra2 = '';
|
||||
if(self::$xchans)
|
||||
$sql_extra2 = " AND (author_xchan IN (" . self::$xchans . ") OR owner_xchan IN (" . self::$xchans . ")) ";
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
WHERE uid = %d
|
||||
AND created <= '%s'
|
||||
AND item_unseen = 1 AND item_wall = 0
|
||||
AND author_xchan != '%s'
|
||||
$item_normal
|
||||
$sql_extra
|
||||
$sql_extra2
|
||||
ORDER BY created DESC LIMIT $limit OFFSET $offset",
|
||||
intval(self::$uid),
|
||||
dbescdate($_SESSION['sse_loadtime']),
|
||||
dbesc(self::$ob_hash)
|
||||
);
|
||||
|
||||
if($items) {
|
||||
$result['network']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1);
|
||||
xchan_query($items);
|
||||
foreach($items as $item) {
|
||||
$result['network']['notifications'][] = Enotify::format($item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$result['network']['offset'] = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
WHERE uid = %d and item_unseen = 1 AND item_wall = 0
|
||||
$item_normal
|
||||
$sql_extra
|
||||
AND author_xchan != '%s'",
|
||||
intval(self::$uid),
|
||||
dbesc(self::$ob_hash)
|
||||
);
|
||||
|
||||
if($r)
|
||||
$result['network']['count'] = intval($r[0]['total']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function bs_home($notifications) {
|
||||
|
||||
$result['home']['notifications'] = [];
|
||||
$result['home']['count'] = 0;
|
||||
|
||||
if(! self::$uid)
|
||||
return $result;
|
||||
|
||||
$limit = intval(self::$limit);
|
||||
$offset = self::$offset;
|
||||
|
||||
$sql_extra = '';
|
||||
if(! (self::$vnotify & VNOTIFY_LIKE))
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
|
||||
$sql_extra2 = '';
|
||||
if(self::$xchans)
|
||||
$sql_extra2 = " AND (author_xchan IN (" . self::$xchans . ") OR owner_xchan IN (" . self::$xchans . ")) ";
|
||||
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
WHERE uid = %d
|
||||
AND created <= '%s'
|
||||
AND item_unseen = 1 AND item_wall = 1
|
||||
AND author_xchan != '%s'
|
||||
$item_normal
|
||||
$sql_extra
|
||||
$sql_extra2
|
||||
ORDER BY created DESC LIMIT $limit OFFSET $offset",
|
||||
intval(self::$uid),
|
||||
dbescdate($_SESSION['sse_loadtime']),
|
||||
dbesc(self::$ob_hash)
|
||||
);
|
||||
|
||||
if($items) {
|
||||
$result['home']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1);
|
||||
xchan_query($items);
|
||||
foreach($items as $item) {
|
||||
$result['home']['notifications'][] = Enotify::format($item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$result['home']['offset'] = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
WHERE uid = %d and item_unseen = 1 AND item_wall = 1
|
||||
$item_normal
|
||||
$sql_extra
|
||||
AND author_xchan != '%s'",
|
||||
intval(self::$uid),
|
||||
dbesc(self::$ob_hash)
|
||||
);
|
||||
|
||||
if($r)
|
||||
$result['home']['count'] = intval($r[0]['total']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function bs_pubs($notifications) {
|
||||
|
||||
$result['pubs']['notifications'] = [];
|
||||
$result['pubs']['count'] = 0;
|
||||
|
||||
if((observer_prohibited(true))) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if(! intval(get_config('system','open_pubstream',1))) {
|
||||
if(! get_observer_hash()) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if(! isset($_SESSION['static_loadtime']))
|
||||
$_SESSION['static_loadtime'] = datetime_convert();
|
||||
|
||||
$limit = intval(self::$limit);
|
||||
$offset = self::$offset;
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$sql_extra = '';
|
||||
if(! (self::$vnotify & VNOTIFY_LIKE))
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
|
||||
$sql_extra2 = '';
|
||||
if(self::$xchans)
|
||||
$sql_extra2 = " AND (author_xchan IN (" . self::$xchans . ") OR owner_xchan IN (" . self::$xchans . ")) ";
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
WHERE uid = %d
|
||||
AND created <= '%s'
|
||||
AND item_unseen = 1
|
||||
AND author_xchan != '%s'
|
||||
AND created > '%s'
|
||||
$item_normal
|
||||
$sql_extra
|
||||
$sql_extra2
|
||||
ORDER BY created DESC LIMIT $limit OFFSET $offset",
|
||||
intval($sys['channel_id']),
|
||||
dbescdate($_SESSION['sse_loadtime']),
|
||||
dbesc(self::$ob_hash),
|
||||
dbescdate($_SESSION['static_loadtime'])
|
||||
);
|
||||
|
||||
if($items) {
|
||||
$result['pubs']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1);
|
||||
xchan_query($items);
|
||||
foreach($items as $item) {
|
||||
$result['pubs']['notifications'][] = Enotify::format($item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$result['pubs']['offset'] = -1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
WHERE uid = %d AND item_unseen = 1
|
||||
AND created > '%s'
|
||||
$item_normal
|
||||
$sql_extra
|
||||
AND author_xchan != '%s'",
|
||||
intval($sys['channel_id']),
|
||||
dbescdate($_SESSION['static_loadtime']),
|
||||
dbesc(self::$ob_hash)
|
||||
);
|
||||
|
||||
if($r)
|
||||
$result['pubs']['count'] = intval($r[0]['total']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
function bs_notify() {
|
||||
|
||||
$result['notify']['notifications'] = [];
|
||||
$result['notify']['count'] = 0;
|
||||
$result['notify']['offset'] = -1;
|
||||
|
||||
if(! self::$uid)
|
||||
return $result;
|
||||
|
||||
$r = q("SELECT * FROM notify WHERE uid = %d AND seen = 0 ORDER BY created DESC",
|
||||
intval(self::$uid)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$result['notify']['notifications'][] = Enotify::format_notify($rr);
|
||||
}
|
||||
$result['notify']['count'] = count($r);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
function bs_intros() {
|
||||
|
||||
$result['intros']['notifications'] = [];
|
||||
$result['intros']['count'] = 0;
|
||||
$result['intros']['offset'] = -1;
|
||||
|
||||
if(! self::$uid)
|
||||
return $result;
|
||||
|
||||
$r = q("SELECT * 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 ORDER BY abook_created DESC LIMIT 50",
|
||||
intval(self::$uid)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$result['intros']['notifications'][] = Enotify::format_intros($rr);
|
||||
}
|
||||
$result['intros']['count'] = count($r);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
function bs_forums() {
|
||||
|
||||
$result['forums']['notifications'] = [];
|
||||
$result['forums']['count'] = 0;
|
||||
$result['forums']['offset'] = -1;
|
||||
|
||||
if(! self::$uid)
|
||||
return $result;
|
||||
|
||||
$forums = get_forum_channels(self::$uid);
|
||||
|
||||
if($forums) {
|
||||
$item_normal = item_normal();
|
||||
|
||||
$sql_extra = '';
|
||||
if(! (self::$vnotify & VNOTIFY_LIKE))
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
|
||||
$fcount = count($forums);
|
||||
$i = 0;
|
||||
|
||||
for($x = 0; $x < $fcount; $x ++) {
|
||||
$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
|
||||
intval(self::$uid),
|
||||
intval(TERM_FORUM),
|
||||
dbesc($forums[$x]['xchan_name'])
|
||||
);
|
||||
|
||||
$p_str = ids_to_querystr($p, 'parent');
|
||||
$p_sql = (($p_str) ? "OR parent IN ( $p_str )" : '');
|
||||
|
||||
$r = q("select mid from item
|
||||
where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $sql_extra $item_normal",
|
||||
intval(self::$uid),
|
||||
dbesc($forums[$x]['xchan_hash']),
|
||||
dbesc($forums[$x]['xchan_hash'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$mids = flatten_array_recursive($r);
|
||||
|
||||
|
||||
foreach($mids as $mid)
|
||||
$b64mids[] = 'b64.' . base64url_encode($mid);
|
||||
|
||||
$forums[$x]['notify_link'] = z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id'];
|
||||
$forums[$x]['name'] = $forums[$x]['xchan_name'];
|
||||
$forums[$x]['addr'] = $forums[$x]['xchan_addr'];
|
||||
$forums[$x]['url'] = $forums[$x]['xchan_url'];
|
||||
$forums[$x]['photo'] = $forums[$x]['xchan_photo_s'];
|
||||
$forums[$x]['unseen'] = count($b64mids);
|
||||
$forums[$x]['private_forum'] = (($forums[$x]['private_forum']) ? 'lock' : '');
|
||||
$forums[$x]['message'] = (($forums[$x]['private_forum']) ? t('Private forum') : t('Public forum'));
|
||||
$forums[$x]['mids'] = json_encode($b64mids);
|
||||
|
||||
unset($forums[$x]['abook_id']);
|
||||
unset($forums[$x]['xchan_hash']);
|
||||
unset($forums[$x]['xchan_name']);
|
||||
unset($forums[$x]['xchan_url']);
|
||||
unset($forums[$x]['xchan_photo_s']);
|
||||
|
||||
$i = $i + count($mids);
|
||||
|
||||
}
|
||||
else {
|
||||
unset($forums[$x]);
|
||||
}
|
||||
}
|
||||
|
||||
$result['forums']['count'] = $i;
|
||||
$result['forums']['notifications'] = array_values($forums);
|
||||
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
function bs_files() {
|
||||
|
||||
$result['files']['notifications'] = [];
|
||||
$result['files']['count'] = 0;
|
||||
$result['files']['offset'] = -1;
|
||||
|
||||
if(! self::$uid)
|
||||
return $result;
|
||||
|
||||
$r = q("SELECT * FROM item
|
||||
WHERE verb = '%s'
|
||||
AND obj_type = '%s'
|
||||
AND uid = %d
|
||||
AND owner_xchan != '%s'
|
||||
AND item_unseen = 1",
|
||||
dbesc(ACTIVITY_POST),
|
||||
dbesc(ACTIVITY_OBJ_FILE),
|
||||
intval(self::$uid),
|
||||
dbesc(self::$ob_hash)
|
||||
);
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
foreach($r as $rr) {
|
||||
$result['files']['notifications'][] = Enotify::format_files($rr);
|
||||
}
|
||||
$result['files']['count'] = count($r);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
function bs_mail() {
|
||||
|
||||
$result['mail']['notifications'] = [];
|
||||
$result['mail']['count'] = 0;
|
||||
$result['mail']['offset'] = -1;
|
||||
|
||||
if(! self::$uid)
|
||||
return $result;
|
||||
|
||||
$r = q("select mail.*, xchan.* from mail left join xchan on xchan_hash = from_xchan
|
||||
where channel_id = %d and mail_seen = 0 and mail_deleted = 0
|
||||
and from_xchan != '%s' order by created desc",
|
||||
intval(self::$uid),
|
||||
dbesc(self::$ob_hash)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$result['mail']['notifications'][] = Enotify::format_mail($rr);
|
||||
}
|
||||
$result['mail']['count'] = count($r);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
function bs_all_events() {
|
||||
|
||||
$result['all_events']['notifications'] = [];
|
||||
$result['all_events']['count'] = 0;
|
||||
$result['all_events']['offset'] = -1;
|
||||
|
||||
if(! self::$uid)
|
||||
return $result;
|
||||
|
||||
$r = q("SELECT * FROM event left join xchan on event_xchan = xchan_hash
|
||||
WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
|
||||
and etype in ( 'event', 'birthday' )
|
||||
ORDER BY dtstart DESC",
|
||||
intval(self::$uid),
|
||||
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval(self::$evdays) . ' days')),
|
||||
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$result['all_events']['notifications'][] = Enotify::format_all_events($rr);
|
||||
}
|
||||
$result['all_events']['count'] = count($r);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function bs_register() {
|
||||
|
||||
$result['register']['notifications'] = [];
|
||||
$result['register']['count'] = 0;
|
||||
$result['register']['offset'] = -1;
|
||||
|
||||
if(! self::$uid && ! is_site_admin())
|
||||
return $result;
|
||||
|
||||
$r = q("SELECT account_email, account_created from account where (account_flags & %d) > 0",
|
||||
intval(ACCOUNT_PENDING)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$result['register']['notifications'][] = Enotify::format_register($rr);
|
||||
}
|
||||
$result['register']['count'] = count($r);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -74,6 +74,29 @@ class Viewconnections extends \Zotlabs\Web\Controller {
|
||||
if(! intval(get_abconfig(\App::$profile['uid'],$rr['xchan_hash'],'their_perms','post_comments'))) {
|
||||
$oneway = true;
|
||||
}
|
||||
|
||||
$perminfo=[];
|
||||
$perminfo['connpermcount']=0;
|
||||
$perminfo['connperms']=t('Accepts').': ';
|
||||
if(intval(get_abconfig(\App::$profile['uid'],$rr['xchan_hash'],'their_perms','post_comments'))) {
|
||||
$perminfo['connpermcount']++;
|
||||
$perminfo['connperms'] .= t('Comments');
|
||||
}
|
||||
if(intval(get_abconfig(\App::$profile['uid'],$rr['xchan_hash'],'their_perms','send_stream'))) {
|
||||
$perminfo['connpermcount']++;
|
||||
$perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ;
|
||||
$perminfo['connperms'] .= t('Stream items');
|
||||
}
|
||||
if(intval(get_abconfig(\App::$profile['uid'],$rr['xchan_hash'],'their_perms','post_wall'))) {
|
||||
$perminfo['connpermcount']++;
|
||||
$perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ;
|
||||
$perminfo['connperms'] .= t('Wall posts');
|
||||
}
|
||||
|
||||
if ($perminfo['connpermcount'] == 0) {
|
||||
$perminfo['connperms'] .= t('Nothing');
|
||||
}
|
||||
|
||||
|
||||
$url = chanlink_hash($rr['xchan_hash']);
|
||||
if($url) {
|
||||
@@ -88,6 +111,7 @@ class Viewconnections extends \Zotlabs\Web\Controller {
|
||||
'sparkle' => '',
|
||||
'itemurl' => $rr['url'],
|
||||
'network' => '',
|
||||
'perminfo' => $perminfo,
|
||||
'oneway' => $oneway
|
||||
);
|
||||
}
|
||||
|
||||
143
Zotlabs/Module/Vote.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Vote extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
$ret = [ 'success' => false, 'message' => EMPTY_STR ];
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
if (! $channel) {
|
||||
$ret['message'] = t('Permission denied.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
|
||||
$fetch = null;
|
||||
$id = argv(1);
|
||||
$response = $_REQUEST['answer'];
|
||||
|
||||
if ($id) {
|
||||
$fetch = q("select * from item where id = %d limit 1",
|
||||
intval($id)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if ($fetch && $fetch[0]['obj_type'] === 'Question') {
|
||||
$obj = json_decode($fetch[0]['obj'],true);
|
||||
|
||||
}
|
||||
else {
|
||||
$ret['message'] = t('Poll not found.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
$valid = false;
|
||||
|
||||
if ($obj['oneOf']) {
|
||||
foreach($obj['oneOf'] as $selection) {
|
||||
// logger('selection: ' . $selection);
|
||||
// logger('response: ' . $response);
|
||||
if($selection['name'] && $selection['name'] === $response) {
|
||||
$valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$choices = [];
|
||||
if ($obj['anyOf']) {
|
||||
foreach ($obj['anyOf'] as $selection) {
|
||||
$choices[] = $selection['name'];
|
||||
}
|
||||
foreach ($response as $res) {
|
||||
if (! in_array($res,$choices)) {
|
||||
$valid = false;
|
||||
break;
|
||||
}
|
||||
$valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $valid) {
|
||||
$ret['message'] = t('Invalid response.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
if (! is_array($response)) {
|
||||
$response = [ $response ];
|
||||
}
|
||||
|
||||
foreach ($response as $res) {
|
||||
|
||||
$item = [];
|
||||
|
||||
|
||||
$item['aid'] = $channel['channel_account_id'];
|
||||
$item['uid'] = $channel['channel_id'];
|
||||
$item['item_origin'] = 1;
|
||||
$item['parent'] = $fetch[0]['id'];
|
||||
$item['parent_mid'] = $fetch[0]['mid'];
|
||||
$item['thr_parent'] = $fetch[0]['mid'];
|
||||
$item['uuid'] = new_uuid();
|
||||
$item['mid'] = z_root() . '/item/' . $item['uuid'];
|
||||
$item['verb'] = 'Create';
|
||||
$item['title'] = $res;
|
||||
$item['author_xchan'] = $channel['channel_hash'];
|
||||
$item['owner_xchan'] = $fetch[0]['author_xchan'];
|
||||
$item['allow_cid'] = '<' . $fetch[0]['author_xchan'] . '>';
|
||||
$item['item_private'] = 1;
|
||||
|
||||
|
||||
$item['obj_type'] = 'Note';
|
||||
$item['author'] = channelx_by_n($channel['channel_id']);
|
||||
|
||||
$item['obj'] = Activity::encode_item($item);
|
||||
|
||||
// now reset the placeholders
|
||||
|
||||
$item['verb'] = ACTIVITY_POST;
|
||||
$item['obj_type'] = 'Answer';
|
||||
unset($item['author']);
|
||||
|
||||
|
||||
$x = item_store($item);
|
||||
|
||||
|
||||
retain_item($fetch[0]['id']);
|
||||
|
||||
if($x['success']) {
|
||||
$itemid = $x['item_id'];
|
||||
Master::Summon( [ 'Notifier', 'like', $itemid ] );
|
||||
}
|
||||
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($itemid)
|
||||
);
|
||||
if ($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
|
||||
}
|
||||
}
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Response submitted. Updates may not appear instantly.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ class Wall_attach extends \Zotlabs\Web\Controller {
|
||||
$def_attach = get_pconfig($channel['channel_id'],'system','attach_path');
|
||||
|
||||
$r = attach_store($channel,(($observer) ? $observer['xchan_hash'] : ''),'', array('source' => 'editor', 'visible' => 0, 'album' => $def_album, 'directory' => $def_attach, 'allow_cid' => '<' . $channel['channel_hash'] . '>'));
|
||||
|
||||
|
||||
if(! $r['success']) {
|
||||
notice( $r['message'] . EOL);
|
||||
killme();
|
||||
@@ -111,9 +111,24 @@ class Wall_attach extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
if(strpos($r['data']['filetype'],'audio') === 0) {
|
||||
$url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path'];
|
||||
echo "\n\n" . '[zaudio]' . $url . '[/zaudio]' . "\n\n";
|
||||
$s = "\n\n" . '[zaudio]' . $url . '[/zaudio]' . "\n\n";
|
||||
}
|
||||
|
||||
if ($r['data']['filetype'] === 'image/svg+xml') {
|
||||
$x = @file_get_contents('store/' . $channel['channel_address'] . '/' . $r['data']['os_path']);
|
||||
if ($x) {
|
||||
$bb = svg2bb($x);
|
||||
if ($bb) {
|
||||
$s .= "\n\n" . $bb;
|
||||
}
|
||||
else {
|
||||
logger('empty return from svgbb');
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger('unable to read svg data file: ' . 'store/' . $channel['channel_address'] . '/' . $r['data']['os_path']);
|
||||
}
|
||||
}
|
||||
|
||||
$s .= "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,13 @@ class Well_known extends \Zotlabs\Web\Controller {
|
||||
case 'dnt-policy.txt':
|
||||
echo file_get_contents('doc/dnt-policy.txt');
|
||||
killme();
|
||||
|
||||
case 'caldav':
|
||||
case 'carddav':
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
|
||||
http_status('301', 'moved permanently');
|
||||
goaway(z_root() . '/cdav');
|
||||
};
|
||||
|
||||
default:
|
||||
if(file_exists(\App::$cmd)) {
|
||||
|
||||
@@ -42,7 +42,7 @@ class Zotfeed extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -13,12 +13,16 @@ class PhotoGd extends PhotoDriver {
|
||||
* @see \Zotlabs\Photo\PhotoDriver::supportedTypes()
|
||||
*/
|
||||
public function supportedTypes() {
|
||||
|
||||
$t = [];
|
||||
|
||||
$t['image/jpeg'] = 'jpg';
|
||||
if(imagetypes() & IMG_PNG)
|
||||
$t['image/png'] = 'png';
|
||||
if(imagetypes() & IMG_GIF)
|
||||
$t['image/gif'] = 'gif';
|
||||
if(imagetypes() & IMG_WEBP)
|
||||
$t['image/webp'] = 'webp';
|
||||
|
||||
return $t;
|
||||
}
|
||||
@@ -142,6 +146,7 @@ class PhotoGd extends PhotoDriver {
|
||||
* @see \Zotlabs\Photo\PhotoDriver::imageString()
|
||||
*/
|
||||
public function imageString() {
|
||||
|
||||
if(! $this->is_valid())
|
||||
return false;
|
||||
|
||||
@@ -150,23 +155,32 @@ class PhotoGd extends PhotoDriver {
|
||||
ob_start();
|
||||
|
||||
switch($this->getType()){
|
||||
|
||||
case 'image/png':
|
||||
$quality = get_config('system', 'png_quality');
|
||||
if((! $quality) || ($quality > 9))
|
||||
$quality = PNG_QUALITY;
|
||||
|
||||
\imagepng($this->image, NULL, $quality);
|
||||
break;
|
||||
|
||||
case 'image/webp':
|
||||
$quality = get_config('system', 'webp_quality');
|
||||
if((! $quality) || ($quality > 100))
|
||||
$quality = WEBP_QUALITY;
|
||||
\imagewebp($this->image, NULL, $quality);
|
||||
break;
|
||||
|
||||
case 'image/jpeg':
|
||||
// gd can lack imagejpeg(), but we verify during installation it is available
|
||||
|
||||
default:
|
||||
$quality = get_config('system', 'jpeg_quality');
|
||||
if((! $quality) || ($quality > 100))
|
||||
$quality = JPEG_QUALITY;
|
||||
|
||||
\imagejpeg($this->image, NULL, $quality);
|
||||
break;
|
||||
}
|
||||
|
||||
$string = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
|
||||
@@ -8,19 +8,16 @@ namespace Zotlabs\Photo;
|
||||
class PhotoImagick extends PhotoDriver {
|
||||
|
||||
public function supportedTypes() {
|
||||
return [
|
||||
|
||||
$ret = [
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/gif' => 'gif',
|
||||
'image/gif' => 'gif'
|
||||
];
|
||||
}
|
||||
if(\Imagick::queryFormats("WEBP"))
|
||||
$ret['image/webp'] = 'webp';
|
||||
|
||||
private function get_FormatsMap() {
|
||||
return [
|
||||
'image/jpeg' => 'JPG',
|
||||
'image/png' => 'PNG',
|
||||
'image/gif' => 'GIF',
|
||||
];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +39,8 @@ class PhotoImagick extends PhotoDriver {
|
||||
* Setup the image to the format it will be saved to
|
||||
*/
|
||||
|
||||
$map = $this->get_FormatsMap();
|
||||
$format = $map[$type];
|
||||
$map = $this->supportedTypes();
|
||||
$format = strtoupper($map[$type]);
|
||||
|
||||
if($this->image) {
|
||||
$this->image->setFormat($format);
|
||||
@@ -58,6 +55,7 @@ class PhotoImagick extends PhotoDriver {
|
||||
* setup the compression here, so we'll do it only once
|
||||
*/
|
||||
switch($this->getType()) {
|
||||
|
||||
case 'image/png':
|
||||
$quality = get_config('system', 'png_quality');
|
||||
if((! $quality) || ($quality > 9))
|
||||
@@ -73,11 +71,21 @@ class PhotoImagick extends PhotoDriver {
|
||||
$quality = $quality * 10;
|
||||
$this->image->setCompressionQuality($quality);
|
||||
break;
|
||||
|
||||
case 'image/jpeg':
|
||||
$quality = get_config('system', 'jpeg_quality');
|
||||
if((! $quality) || ($quality > 100))
|
||||
$quality = JPEG_QUALITY;
|
||||
$this->image->setCompressionQuality($quality);
|
||||
break;
|
||||
|
||||
case 'image/webp':
|
||||
$quality = get_config('system', 'webp_quality');
|
||||
if((! $quality) || ($quality > 100))
|
||||
$quality = WEBP_QUALITY;
|
||||
$this->image->setCompressionQuality($quality);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -720,7 +720,11 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
* @return array Directory[]
|
||||
*/
|
||||
function ChannelList(&$auth) {
|
||||
$ret = array();
|
||||
$ret = [];
|
||||
|
||||
if (intval(get_config('system','cloud_disable_siteroot'))) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$r = q("SELECT channel_id, channel_address, profile.publish FROM channel left join profile on profile.uid = channel.channel_id WHERE channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0",
|
||||
intval(PAGE_HIDDEN)
|
||||
@@ -730,8 +734,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
foreach ($r as $rr) {
|
||||
if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage') && $rr['publish']) {
|
||||
logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA);
|
||||
// @todo can't we drop '/cloud'? It gets stripped off anyway in RedDirectory
|
||||
$ret[] = new Directory('/cloud/' . $rr['channel_address'], $auth);
|
||||
$ret[] = new Directory($rr['channel_address'], $auth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ class File extends DAV\Node implements DAV\IFile {
|
||||
}
|
||||
$gis = @getimagesize($f);
|
||||
logger('getimagesize: ' . print_r($gis,true), LOGGER_DATA);
|
||||
if(($gis) && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG)) {
|
||||
if(($gis) && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG || $gis[2] === IMAGETYPE_WEBP)) {
|
||||
$is_photo = 1;
|
||||
}
|
||||
|
||||
|
||||
25
Zotlabs/Update/_1235.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1235 {
|
||||
|
||||
function run() {
|
||||
|
||||
q("START TRANSACTION");
|
||||
|
||||
$r = q("DELETE FROM app WHERE app_name = '%s' AND app_system = 1",
|
||||
dbesc('Mail')
|
||||
);
|
||||
|
||||
if($r) {
|
||||
q("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
q("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class Router {
|
||||
$routes = Route::get();
|
||||
if($routes) {
|
||||
foreach($routes as $route) {
|
||||
if(is_array($route) && strtolower($route[1]) === $module) {
|
||||
if(is_array($route) && file_exists($route[0]) && strtolower($route[1]) === $module) {
|
||||
include_once($route[0]);
|
||||
if(class_exists($modname)) {
|
||||
$this->controller = new $modname;
|
||||
|
||||
@@ -38,10 +38,15 @@ class SessionHandler implements \SessionHandlerInterface {
|
||||
|
||||
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 false;
|
||||
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
|
||||
|
||||
@@ -82,14 +82,6 @@ class WebServer {
|
||||
if((x($_SESSION, 'authenticated')) || (x($_POST, 'auth-params')) || (\App::$module === 'login'))
|
||||
require('include/auth.php');
|
||||
|
||||
if(! x($_SESSION, 'sysmsg'))
|
||||
$_SESSION['sysmsg'] = array();
|
||||
|
||||
if(! x($_SESSION, 'sysmsg_info'))
|
||||
$_SESSION['sysmsg_info'] = array();
|
||||
|
||||
|
||||
|
||||
if(\App::$install) {
|
||||
/* Allow an exception for the view module so that pcss will be interpreted during installation */
|
||||
if(\App::$module != 'view')
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
|
||||
class Activity_filter {
|
||||
@@ -16,6 +17,46 @@ class Activity_filter {
|
||||
|
||||
$tabs = [];
|
||||
|
||||
if(x($_GET,'dm')) {
|
||||
$dm_active = (($_GET['dm'] == 1) ? 'active' : '');
|
||||
$filter_active = 'dm';
|
||||
}
|
||||
|
||||
if(x($_GET,'verb')) {
|
||||
$events_active = (($_GET['verb'] == '.Event') ? 'active' : '');
|
||||
$polls_active = (($_GET['verb'] == '.Question') ? 'active' : '');
|
||||
$filter_active = (($events_active) ? 'events' : 'polls');
|
||||
}
|
||||
|
||||
|
||||
$tabs[] = [
|
||||
'label' => t('Direct Messages'),
|
||||
'icon' => 'envelope-o',
|
||||
'url' => z_root() . '/' . $cmd . '/?f=&dm=1',
|
||||
'sel' => $dm_active,
|
||||
'title' => t('Show direct (private) messages')
|
||||
];
|
||||
|
||||
if(feature_enabled(local_channel(),'events_tab')) {
|
||||
$tabs[] = [
|
||||
'label' => t('Events'),
|
||||
'icon' => 'calendar',
|
||||
'url' => z_root() . '/' . $cmd . '/?verb=%2EEvent',
|
||||
'sel' => $events_active,
|
||||
'title' => t('Show posts that include events')
|
||||
];
|
||||
}
|
||||
|
||||
if(feature_enabled(local_channel(),'polls_tab')) {
|
||||
$tabs[] = [
|
||||
'label' => t('Polls'),
|
||||
'icon' => 'bar-chart',
|
||||
'url' => z_root() . '/' . $cmd . '/?verb=%2EQuestion',
|
||||
'sel' => $polls_active,
|
||||
'title' => t('Show posts that include polls')
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
if(Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
|
||||
$groups = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
@@ -51,6 +92,7 @@ class Activity_filter {
|
||||
|
||||
if(feature_enabled(local_channel(),'forums_tab')) {
|
||||
$forums = get_forum_channels(local_channel());
|
||||
$channel = App::get_channel();
|
||||
|
||||
if($forums) {
|
||||
foreach($forums as $f) {
|
||||
@@ -61,7 +103,7 @@ class Activity_filter {
|
||||
$fsub[] = [
|
||||
'label' => $f['xchan_name'],
|
||||
'img' => $f['xchan_photo_s'],
|
||||
'url' => (($f['private_forum']) ? $f['xchan_url'] : z_root() . '/' . $cmd . '/?f=&pf=1&cid=' . $f['abook_id']),
|
||||
'url' => (($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' : '')
|
||||
|
||||
280
Zotlabs/Widget/Pinned.php
Normal file
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
/*
|
||||
* Show pinned content
|
||||
*
|
||||
*/
|
||||
|
||||
class Pinned {
|
||||
|
||||
private $allowed_types = 0;
|
||||
private $uid = 0;
|
||||
|
||||
|
||||
/*
|
||||
* @brief Displays pinned items
|
||||
*
|
||||
* @param $uid
|
||||
* @param $types
|
||||
* @return array of results: 'html' string, 'ids' array
|
||||
*
|
||||
*/
|
||||
function widget($uid, $types) {
|
||||
|
||||
$ret = [ 'html' => EMPTY_STR, 'ids' => [] ];
|
||||
|
||||
$this->uid = intval($uid);
|
||||
if(! $this->uid)
|
||||
return $ret;
|
||||
|
||||
$this->allowed_types = get_config('system', 'pin_types', [ ITEM_TYPE_POST ]);
|
||||
|
||||
$items = $this->list($types);
|
||||
|
||||
if(empty($items))
|
||||
return $ret;
|
||||
|
||||
$ret['ids'] = array_column($items, 'id');
|
||||
|
||||
$observer = \App::get_observer();
|
||||
|
||||
foreach($items as $item) {
|
||||
|
||||
$midb64 = 'b64.' . base64url_encode($item['mid']);
|
||||
|
||||
if(in_array($observer['xchan_hash'], get_pconfig($item['uid'], 'pinned_hide', $midb64, [])))
|
||||
continue;
|
||||
|
||||
$author = channelx_by_hash($item['author_xchan']);
|
||||
$owner = channelx_by_hash($item['owner_xchan']);
|
||||
|
||||
$profile_avatar = $author['xchan_photo_m'];
|
||||
$profile_link = chanlink_hash($item['author_xchan']);
|
||||
$profile_name = $author['xchan_name'];
|
||||
|
||||
$commentable = ($item['item_nocomment'] == 0 && $item['comments_closed'] == NULL_DATE ? true : false);
|
||||
|
||||
$location = format_location($item);
|
||||
$isevent = false;
|
||||
$attend = null;
|
||||
$canvote = false;
|
||||
|
||||
$conv_responses = [];
|
||||
|
||||
if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
|
||||
$conv_responses['attendyes'] = [ 'title' => t('Attending','title') ];
|
||||
$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'));
|
||||
$isevent = true;
|
||||
}
|
||||
}
|
||||
|
||||
$consensus = (intval($item['item_consensus']) ? true : false);
|
||||
if($consensus) {
|
||||
$conv_responses['agree'] = [ 'title' => t('Agree','title') ];
|
||||
$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'));
|
||||
$canvote = true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->activity($item, $conv_responses);
|
||||
|
||||
$verified = (intval($item['item_verified']) ? t('Message signature validated') : '');
|
||||
$forged = ((! intval($item['item_verified']) && $item['sig']) ? t('Message signature incorrect') : '');
|
||||
|
||||
$shareable = ((local_channel() && \App::$profile_uid == local_channel() && $item['item_private'] != 1) ? true : false);
|
||||
if ($shareable) {
|
||||
// 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'));
|
||||
}
|
||||
$embed = array( t('Share This'), t('share'));
|
||||
}
|
||||
|
||||
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
|
||||
$is_new = true;
|
||||
|
||||
$body = prepare_body($item,true);
|
||||
|
||||
$str = [
|
||||
'item_type' => intval($item['item_type']),
|
||||
'body' => $body['html'],
|
||||
'tags' => $body['tags'],
|
||||
'categories' => $body['categories'],
|
||||
'mentions' => $body['mentions'],
|
||||
'attachments' => $body['attachments'],
|
||||
'folders' => $body['folders'],
|
||||
'text' => strip_tags($body['html']),
|
||||
'id' => $item['id'],
|
||||
'mids' => json_encode([ $midb64 ]),
|
||||
'isevent' => $isevent,
|
||||
'attend' => $attend,
|
||||
'consensus' => $consensus,
|
||||
'conlabels' => $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']) ),
|
||||
'profile_url' => $profile_link,
|
||||
'name' => $profile_name,
|
||||
'thumb' => $profile_avatar,
|
||||
'via' => t('via'),
|
||||
'title' => $item['title'],
|
||||
'title_tosource' => get_pconfig($item['uid'],'system','title_tosource'),
|
||||
'ago' => relative_date($item['created']),
|
||||
'app' => $item['app'],
|
||||
'str_app' => sprintf( t('from %s'), $item['app'] ),
|
||||
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
|
||||
'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,
|
||||
'divider' => get_pconfig($item['uid'],'system','item_divider'),
|
||||
'attend_title' => t('Attendance Options'),
|
||||
'vote_title' => t('Voting Options'),
|
||||
'is_new' => $is_new,
|
||||
'owner_url' => ($owner['xchan_addr'] != $author['xchan_addr'] ? chanlink_hash($owner['xchan_hash']) : ''),
|
||||
'owner_photo'=> $owner['xchan_photo_m'],
|
||||
'owner_name' => $owner['xchan_name'],
|
||||
'photo' => $body['photo'],
|
||||
'event' => $body['event'],
|
||||
'has_tags' => (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false),
|
||||
// Item toolbar buttons
|
||||
'share' => $share,
|
||||
'embed' => $embed,
|
||||
'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") : ''),
|
||||
// end toolbar buttons
|
||||
'modal_dismiss' => t('Close'),
|
||||
'responses' => $conv_responses
|
||||
];
|
||||
|
||||
$tpl = get_markup_template('pinned_item.tpl');
|
||||
$ret['html'] .= replace_macros($tpl, $str);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @brief List pinned items depend on type
|
||||
*
|
||||
* @param $types
|
||||
* @return array of pinned items
|
||||
*
|
||||
*/
|
||||
private function list($types) {
|
||||
|
||||
if(empty($types) || (! is_array($types)))
|
||||
return [];
|
||||
|
||||
$item_types = array_intersect($this->allowed_types, $types);
|
||||
if(empty($item_types))
|
||||
return [];
|
||||
|
||||
$mids_list = [];
|
||||
|
||||
foreach($item_types as $type) {
|
||||
|
||||
$mids = get_pconfig($this->uid, 'pinned', $type, []);
|
||||
foreach($mids as $mid) {
|
||||
if(! empty($mid) && strpos($mid,'b64.') === 0)
|
||||
$mids_list[] = @base64url_decode(substr($mid,4));
|
||||
}
|
||||
}
|
||||
if(empty($mids_list))
|
||||
return [];
|
||||
|
||||
$r = q("SELECT * FROM item WHERE mid IN ( '%s' ) AND uid = %d AND id = parent AND item_private = 0 ORDER BY created DESC",
|
||||
dbesc(implode(",", $mids_list)),
|
||||
intval($this->uid)
|
||||
);
|
||||
if($r)
|
||||
return $r;
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @brief List activities on item
|
||||
*
|
||||
* @param array $item
|
||||
* @param array $conv_responses
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
private function activity($item, &$conv_responses) {
|
||||
|
||||
foreach(array_keys($conv_responses) as $verb) {
|
||||
|
||||
switch($verb) {
|
||||
case 'like':
|
||||
$v = ACTIVITY_LIKE;
|
||||
break;
|
||||
case 'dislike':
|
||||
$v = ACTIVITY_DISLIKE;
|
||||
break;
|
||||
case 'agree':
|
||||
$v = ACTIVITY_AGREE;
|
||||
break;
|
||||
case 'disagree':
|
||||
$v = ACTIVITY_DISAGREE;
|
||||
break;
|
||||
case 'abstain':
|
||||
$v = ACTIVITY_ABSTAIN;
|
||||
break;
|
||||
case 'attendyes':
|
||||
$v = ACTIVITY_ATTEND;
|
||||
break;
|
||||
case 'attendno':
|
||||
$v = ACTIVITY_ATTENDNO;
|
||||
break;
|
||||
case 'attendmaybe':
|
||||
$v = ACTIVITY_ATTENDMAYBE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM item WHERE parent = %d AND id <> parent AND verb = '%s' AND item_deleted = 0",
|
||||
intval($item['id']),
|
||||
dbesc($v)
|
||||
);
|
||||
if(! $r) {
|
||||
unset($conv_responses[$verb]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$conv_responses[$verb]['count'] = count($r);
|
||||
$conv_responses[$verb]['button'] = get_response_button_text($verb, $conv_responses[$verb]['count']);
|
||||
|
||||
foreach($r as $rr) {
|
||||
|
||||
$author = q("SELECT * FROM xchan WHERE xchan_hash = '%s' LIMIT 1",
|
||||
dbesc($rr['author_xchan'])
|
||||
);
|
||||
$name = (($author && $author[0]['xchan_name']) ? $author[0]['xchan_name'] : t('Unknown'));
|
||||
$conv_responses[$verb]['list'][] = (($rr['author_xchan'] && $author && $author[0]['xchan_photo_s']) ?
|
||||
'<a class="dropdown-item" href="' . chanlink_hash($rr['author_xchan']) . '">' . '<img class="menu-img-1" src="' . zid($author[0]['xchan_photo_s']) . '" alt="' . urlencode($name) . '" /> ' . $name . '</a>' :
|
||||
'<a class="dropdown-item" href="#" class="disabled">' . $name . '</a>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$conv_responses['count'] = count($conv_responses);
|
||||
}
|
||||
}
|
||||
91
boot.php
@@ -50,10 +50,10 @@ require_once('include/attach.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
define ( 'PLATFORM_NAME', 'hubzilla' );
|
||||
define ( 'STD_VERSION', '4.4' );
|
||||
define ( 'STD_VERSION', '4.7.2' );
|
||||
define ( 'ZOT_REVISION', '6.0a' );
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1234 );
|
||||
define ( 'DB_UPDATE_VERSION', 1235 );
|
||||
|
||||
define ( 'PROJECT_BASE', __DIR__ );
|
||||
|
||||
@@ -104,6 +104,11 @@ define ( 'JPEG_QUALITY', 100 );
|
||||
*/
|
||||
define ( 'PNG_QUALITY', 8 );
|
||||
|
||||
/**
|
||||
* App::$config['system']['webp_quality'] from 1 (maximum compressed) to 100 (uncompressed)
|
||||
*/
|
||||
define ( 'WEBP_QUALITY', 80 );
|
||||
|
||||
/**
|
||||
* Language detection parameters
|
||||
*/
|
||||
@@ -899,11 +904,12 @@ class App {
|
||||
// Serve raw files from the file system in certain cases.
|
||||
$filext = pathinfo(self::$cmd, PATHINFO_EXTENSION);
|
||||
|
||||
$serve_rawfiles=[
|
||||
$serve_rawfiles = [
|
||||
'jpg'=>'image/jpeg',
|
||||
'jpeg'=>'image/jpeg',
|
||||
'gif'=>'image/gif',
|
||||
'png'=>'image/png',
|
||||
'webp'=>'image/webp',
|
||||
'ico'=>'image/vnd.microsoft.icon',
|
||||
'css'=>'text/css',
|
||||
'js'=>'text/javascript',
|
||||
@@ -913,7 +919,8 @@ class App {
|
||||
'ttf'=>'font/ttf',
|
||||
'woff'=>'font/woff',
|
||||
'woff2'=>'font/woff2',
|
||||
'svg'=>'image/svg+xml'];
|
||||
'svg'=>'image/svg+xml'
|
||||
];
|
||||
|
||||
if (array_key_exists($filext, $serve_rawfiles) && file_exists(self::$cmd)) {
|
||||
$staticfilecwd = getcwd();
|
||||
@@ -1205,7 +1212,8 @@ class App {
|
||||
'$linkrel' => head_get_links(),
|
||||
'$js_strings' => js_strings(),
|
||||
'$zid' => get_my_address(),
|
||||
'$channel_id' => self::$profile['uid']
|
||||
'$channel_id' => self::$profile['uid'],
|
||||
'$auto_save_draft' => ((feature_enabled(self::$profile['uid'], 'auto_save_draft')) ? "true" : "false")
|
||||
]
|
||||
) . self::$page['htmlhead'];
|
||||
|
||||
@@ -1811,6 +1819,8 @@ function can_view_public_stream() {
|
||||
* @param string $s Text to display
|
||||
*/
|
||||
function notice($s) {
|
||||
|
||||
/*
|
||||
if(! session_id())
|
||||
return;
|
||||
|
||||
@@ -1826,6 +1836,40 @@ function notice($s) {
|
||||
if(App::$interactive) {
|
||||
$_SESSION['sysmsg'][] = $s;
|
||||
}
|
||||
*/
|
||||
|
||||
$hash = get_observer_hash();
|
||||
$sse_id = false;
|
||||
|
||||
if(! $hash) {
|
||||
if(session_id()) {
|
||||
$sse_id = true;
|
||||
$hash = 'sse_id.' . session_id();
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$t = get_xconfig($hash, 'sse', 'timestamp', NULL_DATE);
|
||||
|
||||
if(datetime_convert('UTC', 'UTC', $t) < datetime_convert('UTC', 'UTC', '- 30 seconds')) {
|
||||
set_xconfig($hash, 'sse', 'notifications', []);
|
||||
}
|
||||
|
||||
$x = get_xconfig($hash, 'sse', 'notifications');
|
||||
|
||||
if ($x === false)
|
||||
$x = [];
|
||||
|
||||
if (isset($x['notice']) && in_array($s, $x['notice']['notifications']))
|
||||
return;
|
||||
|
||||
if (App::$interactive) {
|
||||
$x['notice']['notifications'][] = $s;
|
||||
set_xconfig($hash, 'sse', 'notifications', $x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1839,8 +1883,11 @@ function notice($s) {
|
||||
* @param string $s Text to display
|
||||
*/
|
||||
function info($s) {
|
||||
|
||||
/*
|
||||
if(! session_id())
|
||||
return;
|
||||
|
||||
if(! x($_SESSION, 'sysmsg_info'))
|
||||
$_SESSION['sysmsg_info'] = array();
|
||||
|
||||
@@ -1849,6 +1896,40 @@ function info($s) {
|
||||
|
||||
if(App::$interactive)
|
||||
$_SESSION['sysmsg_info'][] = $s;
|
||||
*/
|
||||
|
||||
$hash = get_observer_hash();
|
||||
$sse_id = false;
|
||||
|
||||
if(! $hash) {
|
||||
if(session_id()) {
|
||||
$sse_id = true;
|
||||
$hash = 'sse_id.' . session_id();
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$t = get_xconfig($hash, 'sse', 'timestamp', NULL_DATE);
|
||||
|
||||
if(datetime_convert('UTC', 'UTC', $t) < datetime_convert('UTC', 'UTC', '- 30 seconds')) {
|
||||
set_xconfig($hash, 'sse', 'notifications', []);
|
||||
}
|
||||
|
||||
$x = get_xconfig($hash, 'sse', 'notifications');
|
||||
|
||||
if($x === false)
|
||||
$x = [];
|
||||
|
||||
if(isset($x['info']) && in_array($s, $x['info']['notifications']))
|
||||
return;
|
||||
|
||||
if(App::$interactive) {
|
||||
$x['info']['notifications'][] = $s;
|
||||
set_xconfig($hash, 'sse', 'notifications', $x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,19 +28,19 @@
|
||||
"ext-mbstring" : "*",
|
||||
"ext-xml" : "*",
|
||||
"ext-openssl" : "*",
|
||||
"sabre/dav" : "~3.2",
|
||||
"sabre/dav" : "^4.0",
|
||||
"michelf/php-markdown" : "^1.7",
|
||||
"bshaffer/oauth2-server-php": "^1.9",
|
||||
"ezyang/htmlpurifier": "^4.9",
|
||||
"simplepie/simplepie": "~1.5",
|
||||
"league/html-to-markdown": "^4.4",
|
||||
"pear/text_languagedetect": "^1.0",
|
||||
"commerceguys/intl": "~0.7",
|
||||
"lukasreschke/id3parser": "^0.0.1",
|
||||
"commerceguys/intl": "~1.0.5",
|
||||
"lukasreschke/id3parser": "^0.0.3",
|
||||
"smarty/smarty": "~3.1",
|
||||
"ramsey/uuid": "^3.8",
|
||||
"twbs/bootstrap": "^4.3.1",
|
||||
"blueimp/jquery-file-upload": "^9.25",
|
||||
"blueimp/jquery-file-upload": "^10.3",
|
||||
"desandro/imagesloaded": "^4.1"
|
||||
},
|
||||
"require-dev" : {
|
||||
|
||||
331
composer.lock
generated
@@ -4,20 +4,20 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "f4dce457cd65f92a26d8197617f2f560",
|
||||
"content-hash": "1869554b567d2e0c8d16978035b7197e",
|
||||
"packages": [
|
||||
{
|
||||
"name": "blueimp/jquery-file-upload",
|
||||
"version": "v9.31.0",
|
||||
"version": "v10.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vkhramtsov/jQuery-File-Upload.git",
|
||||
"reference": "2485bf016e1085f0cd8308723064458cb0af5729"
|
||||
"reference": "4677050d31be2da817e1d23d0bacb81fb4b37cb3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/2485bf016e1085f0cd8308723064458cb0af5729",
|
||||
"reference": "2485bf016e1085f0cd8308723064458cb0af5729",
|
||||
"url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/4677050d31be2da817e1d23d0bacb81fb4b37cb3",
|
||||
"reference": "4677050d31be2da817e1d23d0bacb81fb4b37cb3",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@@ -59,7 +59,7 @@
|
||||
"upload",
|
||||
"widget"
|
||||
],
|
||||
"time": "2019-05-24T07:59:46+00:00"
|
||||
"time": "2020-01-04T05:46:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bshaffer/oauth2-server-php",
|
||||
@@ -121,20 +121,20 @@
|
||||
},
|
||||
{
|
||||
"name": "commerceguys/intl",
|
||||
"version": "v0.7.5",
|
||||
"version": "v1.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/commerceguys/intl.git",
|
||||
"reference": "de1435502068393fae4061818e194e4ea61b98d6"
|
||||
"reference": "6a8c7a8da189d51856b642a61aeb8ae5114fec6c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/commerceguys/intl/zipball/de1435502068393fae4061818e194e4ea61b98d6",
|
||||
"reference": "de1435502068393fae4061818e194e4ea61b98d6",
|
||||
"url": "https://api.github.com/repos/commerceguys/intl/zipball/6a8c7a8da189d51856b642a61aeb8ae5114fec6c",
|
||||
"reference": "6a8c7a8da189d51856b642a61aeb8ae5114fec6c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
"php": ">=5.5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikey179/vfsstream": "1.*",
|
||||
@@ -143,7 +143,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.x-dev"
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -161,7 +161,7 @@
|
||||
}
|
||||
],
|
||||
"description": "Internationalization library powered by CLDR data.",
|
||||
"time": "2017-12-29T00:13:05+00:00"
|
||||
"time": "2019-10-22T10:40:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "desandro/imagesloaded",
|
||||
@@ -204,23 +204,23 @@
|
||||
},
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
"version": "v4.10.0",
|
||||
"version": "v4.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ezyang/htmlpurifier.git",
|
||||
"reference": "d85d39da4576a6934b72480be6978fb10c860021"
|
||||
"reference": "a617e55bc62a87eec73bd456d146d134ad716f03"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021",
|
||||
"reference": "d85d39da4576a6934b72480be6978fb10c860021",
|
||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/a617e55bc62a87eec73bd456d146d134ad716f03",
|
||||
"reference": "a617e55bc62a87eec73bd456d146d134ad716f03",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"simpletest/simpletest": "^1.1"
|
||||
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -233,7 +233,7 @@
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL"
|
||||
"LGPL-2.1-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
@@ -247,20 +247,20 @@
|
||||
"keywords": [
|
||||
"html"
|
||||
],
|
||||
"time": "2018-02-23T01:58:20+00:00"
|
||||
"time": "2019-10-28T03:44:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/html-to-markdown",
|
||||
"version": "4.8.1",
|
||||
"version": "4.9.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/html-to-markdown.git",
|
||||
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1"
|
||||
"reference": "1dcd0f85de786f46a7f224a27cc3d709ddd2a68c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/250d1bf45f80d15594fb6b316df777d6d4c97ad1",
|
||||
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1",
|
||||
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/1dcd0f85de786f46a7f224a27cc3d709ddd2a68c",
|
||||
"reference": "1dcd0f85de786f46a7f224a27cc3d709ddd2a68c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -270,7 +270,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"mikehaertl/php-shellcommand": "~1.1.0",
|
||||
"phpunit/phpunit": "4.*",
|
||||
"phpunit/phpunit": "^4.8|^5.7",
|
||||
"scrutinizer/ocular": "~1.1"
|
||||
},
|
||||
"bin": [
|
||||
@@ -279,7 +279,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.9-dev"
|
||||
"dev-master": "4.10-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -292,17 +292,17 @@
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nick Cernis",
|
||||
"email": "nick@cern.is",
|
||||
"homepage": "http://modernnerd.net",
|
||||
"role": "Original Author"
|
||||
},
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Nick Cernis",
|
||||
"email": "nick@cern.is",
|
||||
"homepage": "http://modernnerd.net",
|
||||
"role": "Original Author"
|
||||
}
|
||||
],
|
||||
"description": "An HTML-to-markdown conversion helper for PHP",
|
||||
@@ -311,20 +311,20 @@
|
||||
"html",
|
||||
"markdown"
|
||||
],
|
||||
"time": "2018-12-24T17:21:44+00:00"
|
||||
"time": "2019-12-28T01:32:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lukasreschke/id3parser",
|
||||
"version": "v0.0.1",
|
||||
"version": "v0.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/LukasReschke/ID3Parser.git",
|
||||
"reference": "cd3ba6e8918cc30883f01a3c24281cfe23b8877a"
|
||||
"reference": "62f4de76d4eaa9ea13c66dacc1f22977dace6638"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/LukasReschke/ID3Parser/zipball/cd3ba6e8918cc30883f01a3c24281cfe23b8877a",
|
||||
"reference": "cd3ba6e8918cc30883f01a3c24281cfe23b8877a",
|
||||
"url": "https://api.github.com/repos/LukasReschke/ID3Parser/zipball/62f4de76d4eaa9ea13c66dacc1f22977dace6638",
|
||||
"reference": "62f4de76d4eaa9ea13c66dacc1f22977dace6638",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -346,25 +346,28 @@
|
||||
"php",
|
||||
"tags"
|
||||
],
|
||||
"time": "2016-04-04T09:34:50+00:00"
|
||||
"time": "2016-09-22T15:10:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "michelf/php-markdown",
|
||||
"version": "1.8.0",
|
||||
"version": "1.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/michelf/php-markdown.git",
|
||||
"reference": "01ab082b355bf188d907b9929cd99b2923053495"
|
||||
"reference": "c83178d49e372ca967d1a8c77ae4e051b3a3c75c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/01ab082b355bf188d907b9929cd99b2923053495",
|
||||
"reference": "01ab082b355bf188d907b9929cd99b2923053495",
|
||||
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/c83178d49e372ca967d1a8c77ae4e051b3a3c75c",
|
||||
"reference": "c83178d49e372ca967d1a8c77ae4e051b3a3c75c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": ">=4.3 <5.8"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -392,7 +395,7 @@
|
||||
"keywords": [
|
||||
"markdown"
|
||||
],
|
||||
"time": "2018-01-15T00:49:33+00:00"
|
||||
"time": "2019-12-02T02:32:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
@@ -485,16 +488,16 @@
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
|
||||
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
|
||||
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
|
||||
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -503,7 +506,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -528,48 +531,50 @@
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2018-11-20T15:27:04+00:00"
|
||||
"time": "2019-11-01T11:05:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "3.8.0",
|
||||
"version": "3.9.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/uuid.git",
|
||||
"reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3"
|
||||
"reference": "7779489a47d443f845271badbdcedfe4df8e06fb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/d09ea80159c1929d75b3f9c60504d613aeb4a1e3",
|
||||
"reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/7779489a47d443f845271badbdcedfe4df8e06fb",
|
||||
"reference": "7779489a47d443f845271badbdcedfe4df8e06fb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"paragonie/random_compat": "^1.0|^2.0|9.99.99",
|
||||
"php": "^5.4 || ^7.0",
|
||||
"ext-json": "*",
|
||||
"paragonie/random_compat": "^1 | ^2 | 9.99.99",
|
||||
"php": "^5.4 | ^7 | ^8",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"replace": {
|
||||
"rhumsaa/uuid": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/aspect-mock": "^1.0 | ~2.0.0",
|
||||
"doctrine/annotations": "~1.2.0",
|
||||
"goaop/framework": "1.0.0-alpha.2 | ^1.0 | ~2.1.0",
|
||||
"ircmaxell/random-lib": "^1.1",
|
||||
"jakub-onderka/php-parallel-lint": "^0.9.0",
|
||||
"mockery/mockery": "^0.9.9",
|
||||
"codeception/aspect-mock": "^1 | ^2",
|
||||
"doctrine/annotations": "^1.2",
|
||||
"goaop/framework": "1.0.0-alpha.2 | ^1 | ^2.1",
|
||||
"jakub-onderka/php-parallel-lint": "^1",
|
||||
"mockery/mockery": "^0.9.11 | ^1",
|
||||
"moontoast/math": "^1.1",
|
||||
"php-mock/php-mock-phpunit": "^0.3|^1.1",
|
||||
"phpunit/phpunit": "^4.7|^5.0|^6.5",
|
||||
"squizlabs/php_codesniffer": "^2.3"
|
||||
"paragonie/random-lib": "^2",
|
||||
"php-mock/php-mock-phpunit": "^0.3 | ^1.1",
|
||||
"phpunit/phpunit": "^4.8 | ^5.4 | ^6.5",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "Provides support for PHP Ctype functions",
|
||||
"ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator",
|
||||
"ext-openssl": "Provides the OpenSSL extension for use with the OpenSslGenerator",
|
||||
"ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator",
|
||||
"ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
||||
"moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).",
|
||||
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
||||
"ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid",
|
||||
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
|
||||
},
|
||||
@@ -582,13 +587,21 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Uuid\\": "src/"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Ramsey",
|
||||
"email": "ben@benramsey.com",
|
||||
"homepage": "https://benramsey.com"
|
||||
},
|
||||
{
|
||||
"name": "Marijn Huizendveld",
|
||||
"email": "marijn.huizendveld@gmail.com"
|
||||
@@ -596,11 +609,6 @@
|
||||
{
|
||||
"name": "Thibaud Fabre",
|
||||
"email": "thibaud@aztech.io"
|
||||
},
|
||||
{
|
||||
"name": "Ben Ramsey",
|
||||
"email": "ben@benramsey.com",
|
||||
"homepage": "https://benramsey.com"
|
||||
}
|
||||
],
|
||||
"description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).",
|
||||
@@ -610,20 +618,20 @@
|
||||
"identifier",
|
||||
"uuid"
|
||||
],
|
||||
"time": "2018-07-19T23:38:55+00:00"
|
||||
"time": "2019-12-17T08:18:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabre/dav",
|
||||
"version": "3.2.3",
|
||||
"version": "4.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sabre-io/dav.git",
|
||||
"reference": "a9780ce4f35560ecbd0af524ad32d9d2c8954b80"
|
||||
"reference": "b793fb4ce27cf0f981b540ad771281c430ffe818"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sabre-io/dav/zipball/a9780ce4f35560ecbd0af524ad32d9d2c8954b80",
|
||||
"reference": "a9780ce4f35560ecbd0af524ad32d9d2c8954b80",
|
||||
"url": "https://api.github.com/repos/sabre-io/dav/zipball/b793fb4ce27cf0f981b540ad771281c430ffe818",
|
||||
"reference": "b793fb4ce27cf0f981b540ad771281c430ffe818",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -631,27 +639,28 @@
|
||||
"ext-date": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-spl": "*",
|
||||
"lib-libxml": ">=2.7.0",
|
||||
"php": ">=5.5.0",
|
||||
"php": ">=7.0.0",
|
||||
"psr/log": "^1.0",
|
||||
"sabre/event": ">=2.0.0, <4.0.0",
|
||||
"sabre/http": "^4.2.1",
|
||||
"sabre/uri": "^1.0.1",
|
||||
"sabre/vobject": "^4.1.0",
|
||||
"sabre/xml": "^1.4.0"
|
||||
"sabre/event": "^5.0",
|
||||
"sabre/http": "^5.0",
|
||||
"sabre/uri": "^2.0",
|
||||
"sabre/vobject": "^4.2.0-alpha1",
|
||||
"sabre/xml": "^2.0.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"evert/phpdoc-md": "~0.1.0",
|
||||
"monolog/monolog": "^1.18",
|
||||
"phpunit/phpunit": "> 4.8, <6.0.0",
|
||||
"sabre/cs": "^1.0.0"
|
||||
"phpunit/phpunit": "^6"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": "*",
|
||||
"ext-imap": "*",
|
||||
"ext-pdo": "*"
|
||||
},
|
||||
"bin": [
|
||||
@@ -659,11 +668,6 @@
|
||||
"bin/naturalselection"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Sabre\\DAV\\": "lib/DAV/",
|
||||
@@ -693,28 +697,28 @@
|
||||
"framework",
|
||||
"iCalendar"
|
||||
],
|
||||
"time": "2018-10-19T09:58:27+00:00"
|
||||
"time": "2020-01-10T07:52:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabre/event",
|
||||
"version": "3.0.0",
|
||||
"version": "5.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sabre-io/event.git",
|
||||
"reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534"
|
||||
"reference": "f5cf802d240df1257866d8813282b98aee3bc548"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sabre-io/event/zipball/831d586f5a442dceacdcf5e9c4c36a4db99a3534",
|
||||
"reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534",
|
||||
"url": "https://api.github.com/repos/sabre-io/event/zipball/f5cf802d240df1257866d8813282b98aee3bc548",
|
||||
"reference": "f5cf802d240df1257866d8813282b98aee3bc548",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5"
|
||||
"php": ">=7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "*",
|
||||
"sabre/cs": "~0.0.4"
|
||||
"phpunit/phpunit": ">=6",
|
||||
"sabre/cs": "~1.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -744,38 +748,41 @@
|
||||
"keywords": [
|
||||
"EventEmitter",
|
||||
"async",
|
||||
"coroutine",
|
||||
"eventloop",
|
||||
"events",
|
||||
"hooks",
|
||||
"plugin",
|
||||
"promise",
|
||||
"reactor",
|
||||
"signal"
|
||||
],
|
||||
"time": "2015-11-05T20:14:39+00:00"
|
||||
"time": "2018-03-05T13:55:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabre/http",
|
||||
"version": "v4.2.4",
|
||||
"version": "5.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sabre-io/http.git",
|
||||
"reference": "acccec4ba863959b2d10c1fa0fb902736c5c8956"
|
||||
"reference": "85962a2ed867e7e5beb9f9d3a15cd53cd521a09b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sabre-io/http/zipball/acccec4ba863959b2d10c1fa0fb902736c5c8956",
|
||||
"reference": "acccec4ba863959b2d10c1fa0fb902736c5c8956",
|
||||
"url": "https://api.github.com/repos/sabre-io/http/zipball/85962a2ed867e7e5beb9f9d3a15cd53cd521a09b",
|
||||
"reference": "85962a2ed867e7e5beb9f9d3a15cd53cd521a09b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=5.4",
|
||||
"sabre/event": ">=1.0.0,<4.0.0",
|
||||
"sabre/uri": "~1.0"
|
||||
"php": "^7.0",
|
||||
"sabre/event": ">=4.0 <6.0",
|
||||
"sabre/uri": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.3",
|
||||
"sabre/cs": "~0.0.1"
|
||||
"phpunit/phpunit": "^6.0 || ^7.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": " to make http requests with the Client class"
|
||||
@@ -806,28 +813,27 @@
|
||||
"keywords": [
|
||||
"http"
|
||||
],
|
||||
"time": "2018-02-23T11:10:29+00:00"
|
||||
"time": "2019-11-28T19:35:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabre/uri",
|
||||
"version": "1.2.1",
|
||||
"version": "2.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sabre-io/uri.git",
|
||||
"reference": "ada354d83579565949d80b2e15593c2371225e61"
|
||||
"reference": "18f454324f371cbcabdad3d0d3755b4b0182095d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sabre-io/uri/zipball/ada354d83579565949d80b2e15593c2371225e61",
|
||||
"reference": "ada354d83579565949d80b2e15593c2371225e61",
|
||||
"url": "https://api.github.com/repos/sabre-io/uri/zipball/18f454324f371cbcabdad3d0d3755b4b0182095d",
|
||||
"reference": "18f454324f371cbcabdad3d0d3755b4b0182095d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.7"
|
||||
"php": ">=7"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": ">=4.0,<6.0",
|
||||
"sabre/cs": "~1.0.0"
|
||||
"phpunit/phpunit": "^6"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -857,20 +863,20 @@
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"time": "2017-02-20T19:59:28+00:00"
|
||||
"time": "2019-09-09T23:00:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabre/vobject",
|
||||
"version": "4.2.0",
|
||||
"version": "4.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sabre-io/vobject.git",
|
||||
"reference": "bd500019764e434ff65872d426f523e7882a0739"
|
||||
"reference": "6d7476fbd227ae285029c19ad518cd451336038c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sabre-io/vobject/zipball/bd500019764e434ff65872d426f523e7882a0739",
|
||||
"reference": "bd500019764e434ff65872d426f523e7882a0739",
|
||||
"url": "https://api.github.com/repos/sabre-io/vobject/zipball/6d7476fbd227ae285029c19ad518cd451336038c",
|
||||
"reference": "6d7476fbd227ae285029c19ad518cd451336038c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -953,20 +959,20 @@
|
||||
"xCal",
|
||||
"xCard"
|
||||
],
|
||||
"time": "2019-02-19T13:05:37+00:00"
|
||||
"time": "2019-12-18T19:29:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabre/xml",
|
||||
"version": "1.5.1",
|
||||
"version": "2.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sabre-io/xml.git",
|
||||
"reference": "a367665f1df614c3b8fefc30a54de7cd295e444e"
|
||||
"reference": "f08a58f57e2b0d7df769a432756aa371417ab9eb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sabre-io/xml/zipball/a367665f1df614c3b8fefc30a54de7cd295e444e",
|
||||
"reference": "a367665f1df614c3b8fefc30a54de7cd295e444e",
|
||||
"url": "https://api.github.com/repos/sabre-io/xml/zipball/f08a58f57e2b0d7df769a432756aa371417ab9eb",
|
||||
"reference": "f08a58f57e2b0d7df769a432756aa371417ab9eb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -974,12 +980,11 @@
|
||||
"ext-xmlreader": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"lib-libxml": ">=2.6.20",
|
||||
"php": ">=5.5.5",
|
||||
"php": ">=7.0",
|
||||
"sabre/uri": ">=1.0,<3.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.8|~5.7",
|
||||
"sabre/cs": "~1.0.0"
|
||||
"phpunit/phpunit": "^6"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -1016,20 +1021,20 @@
|
||||
"dom",
|
||||
"xml"
|
||||
],
|
||||
"time": "2019-01-09T13:51:57+00:00"
|
||||
"time": "2019-08-14T15:41:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "simplepie/simplepie",
|
||||
"version": "1.5.2",
|
||||
"version": "1.5.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/simplepie/simplepie.git",
|
||||
"reference": "0e8fe72132dad765d25db4cabc69a91139af1263"
|
||||
"reference": "f4c8246511a38fc9d99a59fb42f61eeeafb31663"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/0e8fe72132dad765d25db4cabc69a91139af1263",
|
||||
"reference": "0e8fe72132dad765d25db4cabc69a91139af1263",
|
||||
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/f4c8246511a38fc9d99a59fb42f61eeeafb31663",
|
||||
"reference": "f4c8246511a38fc9d99a59fb42f61eeeafb31663",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1088,28 +1093,31 @@
|
||||
"rss"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/simplepie/simplepie/tree/1.5.2",
|
||||
"source": "https://github.com/simplepie/simplepie/tree/master",
|
||||
"issues": "https://github.com/simplepie/simplepie/issues"
|
||||
},
|
||||
"time": "2018-08-02T05:43:58+00:00"
|
||||
"time": "2019-11-23T07:05:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "smarty/smarty",
|
||||
"version": "v3.1.33",
|
||||
"version": "v3.1.34",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/smarty-php/smarty.git",
|
||||
"reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f"
|
||||
"reference": "c9f0de05f41b9e52798b268ab1e625fac3b8578c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/dd55b23121e55a3b4f1af90a707a6c4e5969530f",
|
||||
"reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/c9f0de05f41b9e52798b268ab1e625fac3b8578c",
|
||||
"reference": "c9f0de05f41b9e52798b268ab1e625fac3b8578c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "6.4.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
@@ -1117,8 +1125,8 @@
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"libs/bootstrap.php"
|
||||
"classmap": [
|
||||
"libs/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@@ -1144,20 +1152,20 @@
|
||||
"keywords": [
|
||||
"templating"
|
||||
],
|
||||
"time": "2018-09-12T20:54:16+00:00"
|
||||
"time": "2019-02-28T06:42:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.10.0",
|
||||
"version": "v1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "e3d826245268269cd66f8326bd8bc066687b4a19"
|
||||
"reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
|
||||
"reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3",
|
||||
"reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1169,7 +1177,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.9-dev"
|
||||
"dev-master": "1.13-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1185,13 +1193,13 @@
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
},
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
@@ -1202,20 +1210,20 @@
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"time": "2018-08-06T14:22:27+00:00"
|
||||
"time": "2019-11-27T13:56:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twbs/bootstrap",
|
||||
"version": "v4.3.1",
|
||||
"version": "v4.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twbs/bootstrap.git",
|
||||
"reference": "8fa0d3010112dca5dd6dd501173415856001ba8b"
|
||||
"reference": "dca1ab7d877bc4b664b43604657a2b5fbe2b4ecb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twbs/bootstrap/zipball/8fa0d3010112dca5dd6dd501173415856001ba8b",
|
||||
"reference": "8fa0d3010112dca5dd6dd501173415856001ba8b",
|
||||
"url": "https://api.github.com/repos/twbs/bootstrap/zipball/dca1ab7d877bc4b664b43604657a2b5fbe2b4ecb",
|
||||
"reference": "dca1ab7d877bc4b664b43604657a2b5fbe2b4ecb",
|
||||
"shasum": ""
|
||||
},
|
||||
"replace": {
|
||||
@@ -1232,13 +1240,13 @@
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jacob Thornton",
|
||||
"email": "jacobthornton@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Mark Otto",
|
||||
"email": "markdotto@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jacob Thornton",
|
||||
"email": "jacobthornton@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
|
||||
@@ -1253,7 +1261,7 @@
|
||||
"sass",
|
||||
"web"
|
||||
],
|
||||
"time": "2019-02-13T16:01:40+00:00"
|
||||
"time": "2019-11-28T12:59:49+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
@@ -1695,6 +1703,7 @@
|
||||
],
|
||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||
"homepage": "https://github.com/container-interop/container-interop",
|
||||
"abandoned": "psr/container",
|
||||
"time": "2017-02-14T19:40:03+00:00"
|
||||
},
|
||||
{
|
||||
|
||||
4
doc/context/de/appman/help.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Allgemein</dt>
|
||||
<dd>Ändere die individuellen Eigenschaften der ausgewählten App. Kategorien erlauben dir das Einsortieren der Apps um sie in der Liste leichter zu finden. Kundenspezifische Apps, die du oder dein Administrator erstellt haben, können weitere Felder enthalten wie "Preis der App" oder "Ort (URL), um die App zu kaufen". Dies gilt nicht für Hubzilla Core Apps.</dd>
|
||||
</dl>
|
||||
4
doc/context/de/apps/edit/help.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Allgemein</dt>
|
||||
<dd>Ändere oder lösche deine Apps mit Hilfe der Steuerknöpfe neben jedem App-Icon in der Liste.</dd>
|
||||
</dl>
|
||||
6
doc/context/de/apps/help.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Allgemein</dt>
|
||||
<dd>Diese Seite listet alle verfügbaren Apps für Deinen Kanal. Sie enthält die Core Apps wie auch die von Addons. Wenn eine App im <a href='#' onclick='contextualHelpFocus("#app-menu", 1); return false;' title="Klicke zum Öffnen...">App Menü</a> erscheinen soll, dann markiere die App in der Liste mit dem Stern.</dd>
|
||||
<dt>Apps verwalten</dt>
|
||||
<dd>Der Knopf "Apps verwalten" öffnet eine Seite, mit der Du den Namen, die Kategorie und andere Eigenschaften deiner Apps ändern kannst.</dd>
|
||||
</dl>
|
||||
19
doc/context/de/settings/account/help.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Allgemein</dt>
|
||||
<dd>
|
||||
Wenn du dich registriert und dir damit einen <i>Zugang</i> zum Grid verschafft hast, hast du ein <i>Profil</i> und einen <i>Kanal</i> erzeugt.
|
||||
</dd>
|
||||
<dt>Zugang</dt>
|
||||
<dd>
|
||||
Du hast <i>einen</i> Zugang, der sich aus deiner Emailadresse mit deinem Passwort zusammen setzt. Damit greifst du auf dein Profil und deinen Kanal zu.
|
||||
<i>Du authetifizierst dich also einmal auf einem Hub von Hubzilla, und es erlaubt dir beliebig Profile und Kanäle anzulegen und dich mit anderen Leuten zu verbinden.</i>
|
||||
</dd>
|
||||
<dt>Profil</dt>
|
||||
<dd>
|
||||
Du bist sicherlich bei anderen Services im Internet registriert, wie irgendwelchen Foren oder anderen Online Communities. Überall hinterläßt du Informationen über dich wie deinen Geburtstag, dein Alter, dein Land und Ähnliches. Im Gegensatz zu anderen Services erlaubt dir Hubzilla das Anlegen <i>vieler verschiedener Profile</i>. So kannst du ein öffentliches Profil anlegen, das zur allgemeinen Verwendung gedacht ist, ein Profil für deine Arbeitskollegen, deine Familie oder deinen Lebenspartner. <i>Deine Profile sind die grundlegende Information, die du anderen Leuten je nach Beziehung zur Verfügung stellen willst</i>.
|
||||
</dd>
|
||||
<dt>Kanal</dt>
|
||||
<dd>
|
||||
Während der Registrierung hast du deinen ersten <i>Kanal</i> erzeugt. In der Tat, neben verschiedenen Profilen kannst du auch verschiedene Kanäle haben. Das könnte etwas verwirrend sein am Anfang, aber lass uns die Dinge besser verstehen. Du hast also bereits einen Kanal erstellt, den du zum Beispiel für die breite Öffentlichkeit und für den Alltag verwenden kannst. Aber vielleicht bist du ein Bücherwurm, und viele deiner Leser langweilt das. Also eröffnest Du einen <i>zweiten Kanal</i> für Bücherfreunde, in dem ihr euch ungezwungen über Bücher austauschen könnt. Offensichtlich ergibt sich daraus ein neuer Stream von Beiträgen, womöglich mit einem neuen Profil oder neuen Profilen und komplett eigenen Verbindungen oder Kontakten. Einige finden sich in beiden Kanälen, aber die meisten werden wohl nur in einem der Kanäle mitlesen. Du wechselst zwischen den Kanälen wie im richtigen Leben je nachdem, ob du dich auf der Straße mit Leuten triffst oder mit Bücherfreunden sprichst. Im Prinzip können sich deine Kanäle auch untereinander verbinden, du also mit dir selbst sprechen, wenn du das möchtest. <i>Deine Kanäle sind also wie Räume für unterschiedliche Themen, in denen du auf verschiedene Leute triffst</i>.
|
||||
</dd>
|
||||
</dl>
|
||||
19
doc/context/de/settings/channel/help.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Allgemein</dt>
|
||||
<dd>
|
||||
Wenn du dich registriert und dir damit einen <i>Zugang</i> zum Grid verschafft hast, hast du ein <i>Profil</i> und einen <i>Kanal</i> erzeugt.
|
||||
</dd>
|
||||
<dt>Zugang</dt>
|
||||
<dd>
|
||||
Du hast <i>einen</i> Zugang, der sich aus deiner Emailadresse mit deinem Passwort zusammensetzt. Damit greifst du auf dein Profil und deinen Kanal zu.
|
||||
<i>Du authetifizierst dich also einmal auf einem Hub von Hubzilla, und es erlaubt dir beliebig Profile und Kanäle anzulegen und dich mit anderen Leuten zu verbinden.</i>
|
||||
</dd>
|
||||
<dt>Profil</dt>
|
||||
<dd>
|
||||
Du bist sicherlich bei anderen Services im Internet registriert, wie irgendwelchen Foren oder anderen Online Communities. Überall hinterläßt du Informationen über dich wie deinen Geburtstag, dein Alter, dein Land und Ähnliches. Im Gegensatz zu anderen Services erlaubt dir Hubzilla das Anlegen <i>vieler verschiedener Profile</i>. So kannst du ein öffentliches Profil anlegen, das zur allgemeinen Verwendung gedacht ist, ein Profil für deine Arbeitskollegen, deine Familie oder deinen Lebenspartner. <i>Deine Profile sind die grundlegende Information, die du anderen Leuten je nach Beziehung zur Verfügung stellen willst</i>.
|
||||
</dd>
|
||||
<dt>Kanal</dt>
|
||||
<dd>
|
||||
Während der Registrierung hast du deinen ersten <i>Kanal</i> erzeugt. In der Tat, neben verschiedenen Profilen kannst du auch verschiedene Kanäle haben. Das könnte etwas verwirrend sein am Anfang, aber lass uns die Dinge besser verstehen. Du hast also bereits einen Kanal erstellt, den du zum Beispiel für die breite Öffentlichkeit und für den Alltag verwenden kannst. Aber vielleicht bist du ein Bücherwurm und viele deiner Leser langweilt das. Also eröffnest Du einen <i>zweiten Kanal</i> für Bücherfreunde, in dem ihr euch ungezwungen über Bücher austauschen könnt. Offensichtlich ergibt sich daraus ein neuer Stream von Beiträgen, womöglich mit einem neuen Profil oder neuen Profilen und komplett eigenen Verbindungen oder Kontakten. Einige finden sich in beiden Kanälen, aber die meisten werden wohl nur in einem der Kanäle mitlesen. Du wechselst zwischen den Kanälen wie im richtigen Leben je nachdem, ob du dich auf der Straße mit Leuten triffst oder mit Bücherfreunden sprichst. Im Prinzip können sich deine Kanäle auch untereinander verbinden, du also mit dir selbst sprechen, wenn du das möchtest. <i>Deine Kanäle sind also wie Räume für unterschiedliche Themen, in denen du auf verschiedene Leute triffst</i>.
|
||||
</dd>
|
||||
</dl>
|
||||
12
doc/context/de/settings/features/help.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Allgemein</dt>
|
||||
<dd>Diese Seite ermöglicht dir viele zusätzliche Funktionen von Hubzilla einzustellen.</dd>
|
||||
<dt><a href='#' onclick='$("#general-settings-title h3 a").click(); setTimeout((function() {contextualHelpFocus("#general-settings-title", 0)}), 1000); return false;' title="Klicken um das Element anzuzeigen...">Allgemeine Funktionen</a></dt>
|
||||
<dd>Die Einstellungen für allgemeine Funktionen beinhalten Optionen, die relevant sind für deinen Kanal, zum Beispiel bei Webseiten oder Wikis.</dd>
|
||||
<dt><a href='#' onclick='$("#composition-settings-title h3 a").click(); setTimeout((function() {contextualHelpFocus("#composition-settings-title", 0)}), 1000); return false;' title="Klicken um das Element anzuzeigen...">Funktionen für die Beitragserstellung</a></dt>
|
||||
<dd>Diese Funktionen bieten weitere Optionen und Möglichkeiten für die Erstellung neuer Beiträge.</dd>
|
||||
<dt><a href='#' onclick='$("#net_module-settings-title h3 a").click(); setTimeout((function() {contextualHelpFocus("#net_module-settings-title", 0)}), 1000); return false;' title="Klicken um das Element anzuzeigen...">Filterung von Streams</a></dt>
|
||||
<dd>Diese Einstellungen verändern Funktionen, die mit der Filterung und der Ansichtskontrolle enkommender Beiträge verbunden sind.</dd>
|
||||
<dt><a href='#' onclick='$("#tools-settings-title h3 a").click(); setTimeout((function() {contextualHelpFocus("#tools-settings-title", 0)}), 1000); return false;' title="Klicken um das Element anzuzeigen...">Werkzeuge für Beiträge und Kommentare</a></dt>
|
||||
<dd>Hier findest du zusätzliche Werkzeuge um Beiträge zu kategorisieren, und erweiterte Methoden der Kommentierung wie Emojis und Community Tagging.</dd>
|
||||
</dl>
|
||||
20
doc/context/de/settings/tokens/help.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt><a href="/help/member/member_guide#Guest_Access_Tokens">Gastzugangs-Token</a></dt>
|
||||
<dd>
|
||||
Hubzilla verwendet befristete "Wegwerf"-Logins oder "Zot Access Tokens", um das Teilen privater Informationen mit Nichtmitgliedern oder Mitgliedern im Fediverse zu ermöglichen, deren Knoten nur eingeschränkte Möglichkeiten zur Identifizierung bieten. Diese Token können zur Authentifizierung an einem Hub für den Zweck verwendet werden privilegierte oder zugangskontrollierte Ressourcen (Dateien, Fotos, Beiträge, Webseiten, Chaträume, usw.) zugänglich zu machen.
|
||||
</dd>
|
||||
<dt>Einen Token erzeugen</dt>
|
||||
<dd>
|
||||
Das Formular zur Erzeugung von Token benötigt drei Parameter: einen lesbaren Zugangsnamen, ein Passwort oder Zugangs-Token, und optional ein Verfallsdatum. Ein verfallenes Token kann nicht länger verwendet werden und wird von der Liste befristeter Zugänge entfernt. <i>Hinweis</i> Das Passwort-Feld zeigt das Token oder Passwort im Klartext.
|
||||
</dd>
|
||||
<dt>Einen Token teilen</dt>
|
||||
<dd>
|
||||
Wir geben keine Mechanismen für das Teilen der Zugangs-Token vor, jede Kommunikationsmethode ist recht. Alle Token, die du erzeugt hast, werden zu den Listen für die Zugangskontrolle hinzugefügt und können von überall verwendet werden, wo anhand dieser Listen authentifiziert werden kann.
|
||||
|
||||
<b>Ein Beispiel:</b> Ein Besucher trifft auf deine Seite. Er hat ein von dir zur Verfügung gestelltes Zugangs-Token für eines Deiner Fotoalben, das nur von Dir und eben diesem befristeten Zugangsnamen betrachtet werden darf. Der Besucher erhält zunächst keinen Zugang.
|
||||
|
||||
Nun wählt er "Login" aus der Navigation und erhält die Loginseite angezeigt, in die er seine Zugangsdaten eingibt. Ab sofort erhält er Zugang zum Fotoalbum.
|
||||
|
||||
Alternativ kannst du einen Link mit deinem Besucher teilen, dessen URL um den Parameter "&zat=abc123" erweitert ist, wobei "abc123" das Zugangs-Token oder das Passwort für den befristeten Login ist. Mit dieser Erweiterung ist kein Login erforderlich, der Besucher erhält sofort den Zugang.
|
||||
</dd>
|
||||
</dl>
|
||||
@@ -1,3 +1,12 @@
|
||||
[h2]Database updates[/h2]
|
||||
|
||||
In the [observer.baseurl]/admin/dbsync page the administrator can check if any update was not successful and, if so, retry it.
|
||||
|
||||
If an update has failed but doesn't register as failed for some reason, the administrator can attempt to re-execute the update. For example for DB update #1999, by visiting the webpage:
|
||||
|
||||
https://hubzilla.com.bradmin/dbsync/1999
|
||||
|
||||
|
||||
[h2]Database Tables[/h2][table border=1][tr][th]Table[/th][th]Description[/th][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_abconfig]abconfig[/zrl][/td][td]arbitrary storage for connections of local channels[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_abook]abook[/zrl][/td][td]connections of local channels[/td][/tr]
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
[h1]Advanced Configurations for Administrators[/h1]
|
||||
$Projectname contains many configuration options hidden from the main admin panel.
|
||||
|
||||
These are generally options considered too niche, confusing, or advanced for the average member. These settings can be activated from the the top level web directory with the syntax
|
||||
[i]This document assumes you're an administrator.[/i]
|
||||
|
||||
$Projectname contains many configuration options hidden from the main admin panel. These are generally options considered too niche, advanced or prone do confusion.
|
||||
|
||||
These settings can be modified through the shell, from the the top level web directory, with the syntax:
|
||||
|
||||
[code]util/config cat key value[/code]
|
||||
for a site configuration, or
|
||||
@@ -9,8 +12,13 @@ for a site configuration, or
|
||||
[code]util/pconfig channel_id cat key value[/code]
|
||||
for a member configuration.
|
||||
|
||||
This document assumes you're an administrator.
|
||||
[h2]pconfig[/h2][dl terms="mb"]
|
||||
For a site configuration, another option is to add a line to .htconfig.php, with the syntax:
|
||||
[code]App::$config['cat']['key'] = 'value';[/code]
|
||||
|
||||
|
||||
[h2]Member configuration (pconfig)[/h2]
|
||||
|
||||
[dl terms="mb"]
|
||||
[*= system.always_my_theme ] Always use your own theme when viewing channels on the same hub. This will break in some quite imaginative ways when viewing channels with theme dependent Comanche.
|
||||
[*= system.blocked ] An array of xchans blocked by this channel. Technically, this is a hidden config and does belong here, however, addons (notably superblock) have made this available in the UI.
|
||||
[*= system.default_cipher ] Set the default cipher used for E2EE items.
|
||||
@@ -31,7 +39,10 @@ Options are:
|
||||
[*= system.anonymous_comments ] By default or if set to 1, custom permissions can be set to allow anonymous (moderated) comments like WordPress, moderated by the channel owner. If set to 0, no member of your site can select or enable this.
|
||||
[*= system.user_scalable ] Determine if the app is scalable on touch screens. Defaults to on, to disable, set to zero - real zero, not just false.
|
||||
[/dl]
|
||||
[h2]Site config[/h2][dl terms="mb"]
|
||||
|
||||
[h2]Site configuration[/h2]
|
||||
|
||||
[dl terms="mb"]
|
||||
[*= randprofile.check ] When requesting a random profile, check that it actually exists first
|
||||
[*= randprofile.retry ] Number of times to retry getting a random profile
|
||||
[*= system.admin_email ] Specifies the administrator's email for this site. This is initially set during install.
|
||||
@@ -62,11 +73,13 @@ Options are:
|
||||
[*= system.max_tagged_forums ] Spam prevention. Limits the number of tagged forums which are recognised in any post. Default is 2. Only the first 'n' tags will be delivered as forums, the others will not cause any delivery.
|
||||
[*= system.minimum_feedcheck_minutes ] The minimum interval between polling RSS feeds. If this is lower than the cron interval, feeds will be polled with each cronjob. Defaults to 60 if not set. The site setting can also be over-ridden on a channel by channel basis by a service class setting aptly named 'minimum_feedcheck_minutes'.
|
||||
[*= system.no_age_restriction ] Do not restrict registration to people over the age of 13. This carries legal responsibilities in many countries to require that age be provided and to block all personal information from minors, so please check your local laws before changing.
|
||||
[*= system.object_cache_days] Set how long is cached embedded content can be used without refetching. Default is 30 days.
|
||||
[*= system.openssl_conf_file ] Specify a file containing OpenSSL configuration. Needed in some Windows installations to locate the openssl configuration file on the system. Read the code first. If you can't read the code, don't play with it.
|
||||
[*= system.openssl_encrypt ] Use openssl encryption engine, default is false (uses mcrypt for AES encryption)
|
||||
[*= system.optimize_items ] Runs optimise_table during some tasks to keep your database nice and defragmented. This comes at a performance cost while the operations are running, but also keeps things a bit faster while it's not. There also exist CLI utilities for performing this operation, which you may prefer, especially if you're a large site.
|
||||
[*= system.override_poll_lockfile ] Ignore the lock file in the poller process to allow more than one process to run at a time.
|
||||
[*= system.paranoia ] As the pconfig, but on a site-wide basis. Can be overwritten by member settings.
|
||||
[*= system.pin_types ] Array of allowed item types for pinning. Defaults depend on module but can be redifined here.
|
||||
[*= system.photo_cache_time ] How long to cache photos, in seconds. Default is 86400 (1 day). Longer time increases performance, but it also means it takes longer for changed permissions to apply.
|
||||
[*= system.platform_name ] What to report as the platform name in webpages and statistics. (*) Must be set in .htconfig.php
|
||||
[*= system.rating_enabled ] Distributed reputation reporting and data collection. This feature is currently being re-worked.
|
||||
@@ -87,13 +100,19 @@ Options are:
|
||||
[*= system.workflow_channel_next ] The page to direct new members to immediately after creating a channel.
|
||||
[*= system.workflow_register_next ] The page to direct members to immediately after creating an account (only when auto_channel_create or UNO is enabled).
|
||||
[/dl]
|
||||
[h2]Directory config[/h2]
|
||||
[h3]Directory search defaults[/h3][dl terms="mb"]
|
||||
|
||||
|
||||
[h3]Directory config[/h3]
|
||||
|
||||
[h4]Directory search defaults[/h4]
|
||||
|
||||
[dl terms="mb"]
|
||||
[*= directory.globaldir ] 0 or 1. Default 0. If you visit the directory on a site you'll just see the members of that site by default. You have to go through an extra step to see the people in the rest of the network; and by doing so there's a clear delineation that these people *aren't* members of that site but of a larger network.
|
||||
[*= directory.pubforums ] 0 or 1. Public forums [i]should[/i] be default 0.
|
||||
[*= directory.safemode ] 0 or 1.
|
||||
[/dl]
|
||||
[h3]Directory server configuration[/h3][i](see [zrl=[baseurl]/help/directories]help/directories[/zrl])[/i]
|
||||
|
||||
[h4]Directory server configuration[/h4][i](see [zrl=[baseurl]/help/directories]help/directories[/zrl])[/i]
|
||||
|
||||
[dl terms="mb"]
|
||||
[*= system.directory_mode ]
|
||||
|
||||
1
doc/hook/activity_decode_mapper.bb
Normal file
@@ -0,0 +1 @@
|
||||
[h2]activity_decode_mapper[/h2]
|
||||
1
doc/hook/activity_mapper.bb
Normal file
@@ -0,0 +1 @@
|
||||
[h2]activity_mapper[/h2]
|
||||
1
doc/hook/activity_obj_decode_mapper.bb
Normal file
@@ -0,0 +1 @@
|
||||
[h2]activity_obj_decode_mapper[/h2]
|
||||
1
doc/hook/activity_obj_mapper.bb
Normal file
@@ -0,0 +1 @@
|
||||
[h2]activity_obj_mapper[/h2]
|
||||
11
doc/hook/comments_are_now_closed.bb
Normal file
@@ -0,0 +1,11 @@
|
||||
[h3]comments_are_now_closed[/h3]
|
||||
|
||||
Called when deciding whether or not commenting is closed for an item.
|
||||
|
||||
|
||||
Hook data (array):
|
||||
item => posted item
|
||||
closed => 'unset'
|
||||
|
||||
|
||||
To over-ride the default behaviour, change closed to true or false
|
||||
1
doc/hook/encode_object.bb
Normal file
@@ -0,0 +1 @@
|
||||
[h2]encode_object[/h2]
|
||||
1
doc/hook/fetch_and_store.bb
Normal file
@@ -0,0 +1 @@
|
||||
[h2]fetch_and_store[/h2]
|
||||
@@ -34,6 +34,18 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
|
||||
[zrl=[baseurl]/help/hook/activity_filter]activity_filter[/zrl]
|
||||
Called when generating the list of filters for the network page
|
||||
|
||||
[zrl=[baseurl]/help/hook/activity_filter]activity_mapper[/zrl]
|
||||
Called when determining the activity type for transmission.
|
||||
|
||||
[zrl=[baseurl]/help/hook/activity_filter]activity_decode_mapper[/zrl]
|
||||
Called when determining the activity type for transmission.
|
||||
|
||||
[zrl=[baseurl]/help/hook/activity_filter]activity_obj_mapper[/zrl]
|
||||
Called when determining the object type for transmission.
|
||||
|
||||
[zrl=[baseurl]/help/hook/activity_filter]activity_obj_decode_mapper[/zrl]
|
||||
Called when determining the object type for transmission.
|
||||
|
||||
[zrl=[baseurl]/help/hook/activity_order]activity_order[/zrl]
|
||||
Called when generating the list of order options for the network page
|
||||
|
||||
@@ -142,6 +154,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
|
||||
[zrl=[baseurl]/help/hook/comment_buttons]comment_buttons[/zrl]
|
||||
Called when rendering the edit buttons for comments
|
||||
|
||||
[zrl=[baseurl]/help/hook/comments_are_now_closed]comments_are_now_closed[/zrl]
|
||||
Called when deciding whether or not to present a comment box for a post
|
||||
|
||||
[zrl=[baseurl]/help/hook/connect_premium]connect_premium[/zrl]
|
||||
Called when connecting to a premium channel
|
||||
|
||||
@@ -232,6 +247,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
|
||||
[zrl=[baseurl]/help/hook/drop_item]drop_item[/zrl]
|
||||
called when an 'item' is removed
|
||||
|
||||
[zrl=[baseurl]/help/hook/encode_object]encode_object[/zrl]
|
||||
called when encoding an object for transmission.
|
||||
|
||||
[zrl=[baseurl]/help/hook/enotify]enotify[/zrl]
|
||||
called before any notification
|
||||
|
||||
@@ -241,6 +259,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
|
||||
[zrl=[baseurl]/help/hook/enotify_store]enotify_store[/zrl]
|
||||
called when storing a notification record
|
||||
|
||||
[zrl=[baseurl]/help/hook/enotify_store_end]enotify_store_end[/zrl]
|
||||
called after a notification record has been stored
|
||||
|
||||
[zrl=[baseurl]/help/hook/event_created]event_created[/zrl]
|
||||
called when an event record is created
|
||||
|
||||
@@ -262,6 +283,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
|
||||
[zrl=[baseurl]/help/hook/feature_settings_post]feature_settings_post[/zrl]
|
||||
called from settings page when posting from 'addon/feature settings'
|
||||
|
||||
[zrl=[baseurl]/help/hook/fetch_and_store]fetch_and_store[/zrl]
|
||||
called to allow filtering of 'decoded' items before storage.
|
||||
|
||||
[zrl=[baseurl]/help/hook/file_thumbnail]file_thumbnail[/zrl]
|
||||
called when generating thumbnail images for cloud page in 'view tiles' mode
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
<div class="flex-column">
|
||||
<a class="nav-link" href="/help/admin/administrator_guide">Guide</a>
|
||||
<a class="nav-link" href="/help/admin/hub_snapshots">Hub Snapshots</a>
|
||||
<a class="nav-link" href="/help/database">Database Tables</a>
|
||||
<a class="nav-link" href="/help/database">Database</a>
|
||||
<a class="nav-link" href="/help/hidden_configs">Extra configs</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
BIN
images/audio.gif
|
Before Width: | Height: | Size: 559 B |
|
Before Width: | Height: | Size: 83 B |
|
Before Width: | Height: | Size: 138 B |
|
Before Width: | Height: | Size: 311 B |
|
Before Width: | Height: | Size: 111 B |
|
Before Width: | Height: | Size: 138 B |
|
Before Width: | Height: | Size: 311 B |
|
Before Width: | Height: | Size: 451 B |
BIN
images/bug-x.gif
|
Before Width: | Height: | Size: 134 B |