Compare commits

..

616 Commits
5.6 ... 6.4

Author SHA1 Message Date
Mario
fe7ecede70 Merge branch '6.4RC' 2021-11-09 09:10:19 +00:00
Mario
089708ab9f version 6.4 2021-11-09 09:08:52 +00:00
Mario
daa844c038 Merge branch 'dev' into 6.4RC 2021-11-09 09:07:55 +00:00
Mario
4049992228 update changelog 2021-11-09 09:07:37 +00:00
Mario
7c576c91b7 Merge branch 'dev' into 6.4RC 2021-10-30 09:08:32 +00:00
Mario
17bd364614 remove logging 2021-10-30 09:07:56 +00:00
Mario
25ffd39519 Merge branch 'dev' into 6.4RC 2021-10-30 09:05:24 +00:00
Mario
acfa527e3e css fixes 2021-10-30 09:04:50 +00:00
Mario
b512416cb3 fix version 2021-10-28 14:17:53 +00:00
Mario
bd116c53a1 update changelog 2021-10-28 14:14:20 +00:00
Mario
1251fca256 remove mcrypt from the docs 2021-10-27 18:42:25 +00:00
Mario
b2fe21709c update sbom 2021-10-27 12:13:47 +00:00
Mario
c082d12b59 bump dev version 2021-10-27 08:11:09 +00:00
Mario
9a4ca44255 version and strings 2021-10-27 08:05:57 +00:00
Mario
6fce9a41b0 remove logging 2021-10-25 08:12:17 +00:00
Mario
65acdd7b15 mod regate: auto-connect the invitee with the inviter if auto channel create is enabled (default). fix issue where the default group was not set in the return array of create_identity() 2021-10-25 08:03:12 +00:00
Mario
a209374cbd invite: fix variable name in template and do not substitute the Â@ in the webfinger address with @+ 2021-10-22 09:52:30 +00:00
Mario
c1bb87db98 mod item: cleanup and remove some unused variables 2021-10-22 08:16:19 +00:00
Mario
8bae40449f remove library/urlify and use vendor/jbroadway/urlify instead 2021-10-22 08:07:19 +00:00
Mario
bc3bb4694a mod import: formating 2021-10-22 07:50:35 +00:00
Mario
22588e58f3 install urlify via composer 2021-10-22 07:46:30 +00:00
Mario
69ba4eb055 whitespace 2021-10-22 07:27:37 +00:00
Mario
687b9fb6a2 comment out warning about db version differences - it is not relevant 2021-10-22 07:26:30 +00:00
Mario
9b9ca9695c import_items: cleanup 2021-10-21 10:36:31 +00:00
Mario
6357c69868 import_items: provide a possibility to import exported zip files by year 2021-10-21 10:29:44 +00:00
Mario
15cb7ab7a1 nativeWikiPage: more whitespace and cleanup 2021-10-20 19:54:59 +00:00
Mario Vavti
2c741bd24d fix for issue #1640 - use item_store() instead of post_activity_item() which is checking for post_comment permission which we might not have in this case. item_store() requires slightly more data but basically does the same. Also some minor improvements and whitespace changes. 2021-10-20 21:35:42 +02:00
Mario
3f72a3beb6 fix xchan vcard rendering 2021-10-20 09:57:45 +00:00
Mario
42de18d96d fix dutch registration email verification email template
(cherry picked from commit c7515b8687)
2021-10-20 10:09:19 +02:00
Mario
4bdbdab399 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-20 08:08:09 +00:00
Mario
c7515b8687 fix dutch registration email verification email template 2021-10-20 08:07:06 +00:00
Mario
c79e39a488 improve code comments 2021-10-20 08:06:29 +00:00
Mario
d639104b71 invite: use the actual set language and check if we have a template for it
(cherry picked from commit c66a5ba732)
2021-10-18 21:44:06 +02:00
Mario
c66a5ba732 invite: use the actual set language and check if we have a template for it 2021-10-18 21:41:08 +02:00
Mario
79f9b49dd7 provide tags indicating the supported protocols in the actor object and probe for zot6 if appropiate 2021-10-18 07:53:45 +00:00
Mario
8b542c250a mod invite: skip the pre-check for valid email 2021-10-16 20:07:34 +00:00
Mario
55237683d2 xrd whitespace 2021-10-16 19:24:58 +00:00
Mario
27401794e1 rename functions after heavy lifting and expand custom sections to all possible sections 2021-10-16 18:10:23 +00:00
Mario
862a7c2dba manifest: remove orientation so that os default will be used and add default theme_color 2021-10-16 14:03:35 +00:00
Mario
bb31a4620e notes: provide translateable strings 2021-10-15 19:30:38 +00:00
Mario
7aaade8b23 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-15 19:17:31 +00:00
Mario
a622f533ad some heavylifting on manual item export 2021-10-15 19:17:06 +00:00
Max Kostikov
0dd27dabd6 Merge branch 'dev' into 'dev'
Update Russian translation

See merge request hubzilla/core!1994
2021-10-15 15:08:16 +00:00
Max Kostikov
8ab464acf2 Update Russian translation 2021-10-15 16:55:21 +02:00
Mario
db18438db2 escape_tags only once 2021-10-15 08:15:41 +00:00
Mario
f885f98611 use the proprt syntax 2021-10-14 18:59:41 +00:00
Mario
9b8b85545f Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-14 18:16:27 +00:00
Mario
532b479f96 provide local copies of the w3.org jsonld documents - addresses issue #1637 2021-10-14 18:15:38 +00:00
Mario
422dfca6d7 fix cacert missing some certificates after last update 2021-10-14 18:13:02 +00:00
Mario
c3d1474f59 Merge branch 'dev' into 'dev'
Support IDNA URLs embedding

See merge request hubzilla/core!1990
2021-10-14 13:16:18 +00:00
Max Kostikov
99873504e4 Support IDNA URLs embedding 2021-10-14 13:16:16 +00:00
Mario
138a67298d version 2021-10-13 11:36:18 +00:00
Mario
aca1551e86 implement AS representation of photos and albums, cleanup and minor fixes 2021-10-13 09:23:59 +00:00
Mario
ca32850a32 fix image object as per AS2 2021-10-12 20:06:11 +00:00
Mario
ba6f069997 HTTPSig: do not query for hubloc_addr 2021-10-12 19:05:21 +00:00
Mario
c6c6b52ccd notes: minor css fix 2021-10-12 18:59:52 +00:00
Mario
96c334e730 bbcode for notes app 2021-10-12 11:27:36 +00:00
Mario
3e503ec3a3 Revert "httpsig: add parentheses"
This reverts commit e455fae334.
2021-10-12 11:25:44 +00:00
Mario
e455fae334 httpsig: add parentheses 2021-10-12 11:25:24 +00:00
Mario
29f3dc2fa3 notifications_widget: fix regression hiding the #nav- * -sub element when there are no more notifications 2021-10-11 09:12:05 +00:00
Mario
aa41b16757 look for hubloc_id_url or hubloc_hash, otherwise we will always fetch the key from the net on platforms where those are different (e.g. mastodon). 2021-10-11 07:41:12 +00:00
Mario
f4d59abe41 streamline logic 2021-10-10 21:13:30 +00:00
Mario
18de58fd8b HTTPSig: cleanup, add some doco and implement missing force mechanism for fetching keys 2021-10-10 21:00:22 +00:00
Mario
4c2b188f8b if we do not have a display path, we are looking at the root directory 2021-10-10 18:16:13 +00:00
Mario
08f65420f4 messages widget: show user-plus icon for connection requests 2021-10-10 09:49:12 +00:00
Mario
b90228b319 make sure we do not select removed channels as importer in onepoll 2021-10-10 08:37:44 +00:00
Mario
ad2c165f26 bbcode: deal with codeblocks before we escape other tags 2021-10-10 08:10:49 +00:00
Mario
af5218593a update composer libs 2021-10-10 07:59:31 +00:00
Mario
f19acd9f50 remove redundant variable and provide missing phpdoc 2021-10-10 07:56:42 +00:00
Mario
59940e7f05 make sure to not include removed channels in xrd or webfinger queries 2021-10-09 19:46:27 +00:00
Mario Vavti
094536e633 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-09 20:08:23 +02:00
Mario Vavti
4f2a439873 mod import: only run automatic content and files import if api version is compatible 2021-10-09 20:08:11 +02:00
Mario
63bdab2b5f use Libzot::fetch_conversation to fetch conversations from search and add an optional force argument to process_delivery 2021-10-09 15:00:21 +00:00
Mario
14733f8482 more bs5 fixes 2021-10-09 08:58:11 +00:00
Mario
b830bbd084 remove hz_syslog and deal with intro notifications in the messages widget 2021-10-08 17:35:36 +00:00
Mario
c1894c5a39 bump version 2021-10-08 13:01:09 +00:00
Mario
e91e488e1f Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-08 12:26:08 +00:00
Mario
e6dac085cb update composer libs 2021-10-08 12:24:19 +00:00
Mario
5023a5b56b Merge branch 'Aksel-dev-patch-31902' into 'dev'
German roles.bb

See merge request hubzilla/core!1992
2021-10-06 15:22:43 +00:00
Aksel K
32d37d1178 Aktualisieren doc/de/roles.bb 2021-10-06 15:12:55 +00:00
Aksel K
848221649e Neue Datei hochladen 2021-10-06 14:56:01 +00:00
Mario
f5f357060b fix alt_pager() 2021-10-06 14:32:49 +00:00
Mario
98eea41865 fix drop_query_params() if no query params are left 2021-10-06 14:32:25 +00:00
Mario
8ac529f5ae simplify 2021-10-06 08:43:40 +00:00
Mario
b5fed08dd4 really de-duplicate entries for dead hubs 2021-10-06 08:33:10 +00:00
Mario
9bfcaf2669 do not show duplicate entries for dead hubs 2021-10-06 08:05:16 +00:00
Mario Vavti
af05ee7e1c Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-06 09:40:15 +02:00
Mario
3918439020 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-06 07:39:34 +00:00
Mario
3b71e115a4 implement sync logic in mod appman 2021-10-06 07:39:10 +00:00
Mario Vavti
c33660a015 move sync logic for apps to mod appman. this way we can re-use the functions without creating sync loops. 2021-10-06 09:36:14 +02:00
Max Kostikov
7963d4cb8f Merge branch 'ab-dev' into 'dev'
Polish translation: fixes and updates

See merge request hubzilla/core!1989
2021-10-05 18:27:42 +00:00
Mario
16281e0e7f disable app sync due to a possible loop 2021-10-04 19:16:38 +00:00
Mario Vavti
72c58e60d7 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-04 20:32:32 +02:00
Mario Vavti
4b48ff2868 also sync the undestroy action 2021-10-04 20:32:19 +02:00
Mario
8e212d30d0 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-04 18:21:08 +00:00
Mario
b9ae396e74 unset id before syncing 2021-10-04 18:20:51 +00:00
Mario Vavti
3a38946f8a more app sync 2021-10-04 20:19:16 +02:00
Andrzej Budziński
d0d3a5454e Polish translation: fixes and updates 2021-10-04 19:24:16 +02:00
Mario Vavti
04c6d77d2c set the sync flag to true 2021-10-04 14:14:30 +02:00
Mario Vavti
c2c5730d00 more app sync fixes 2021-10-04 14:08:39 +02:00
Mario Vavti
21a6dffd5f Revert "more app sync fixes"
This reverts commit 7430989212.
2021-10-04 13:54:45 +02:00
Mario Vavti
7430989212 more app sync fixes 2021-10-04 13:41:54 +02:00
Mario Vavti
2e26a13f81 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-04 13:31:30 +02:00
Mario Vavti
404ebd4d5e app sync fixes - part 2 2021-10-04 13:31:26 +02:00
Mario
11ea7bf0fc app sync fixes - part 1 2021-10-04 11:25:52 +00:00
Mario
6da7fe7d27 provide system app sync 2021-10-04 09:24:13 +00:00
Mario
538e540531 commment out deprecated code 2021-10-04 08:46:56 +00:00
Mario
53138f4b09 fix typo 2021-10-04 08:32:36 +00:00
Mario
3d71367f30 add pem 2021-10-04 08:31:00 +00:00
Mario
bb52ff9b4b fix site lookup and minor cleanup 2021-10-04 08:28:57 +00:00
Mario
ab5b82221c update certs 2021-10-03 18:24:26 +00:00
Mario
5c3b89a68b mod locs: do not show drop icon for local clones and get rid of redundant for loop 2021-10-03 17:48:00 +00:00
Mario
da923d7749 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-03 16:54:04 +00:00
Mario
55d905fdd9 clone channel delete issues - part 2 2021-10-03 16:53:48 +00:00
Mario Vavti
4ba70a3fae clone channel delete issues - part 1 2021-10-03 18:52:14 +02:00
Mario
a5835b0e85 disable pg tests 2021-10-03 12:59:10 +00:00
Mario
ed4e5c9bcf version 6.2.2 2021-10-03 12:40:48 +00:00
Mario
d8793de629 make sure we have a sender here
(cherry picked from commit 0722188ea6)
2021-10-03 14:38:59 +02:00
Mario
f45cb38cd3 make sure to return if we have no xchan here
(cherry picked from commit d6f81e139a)
2021-10-03 14:38:29 +02:00
Mario
0722188ea6 make sure we have a sender here 2021-10-03 12:36:17 +00:00
Mario
d6f81e139a make sure to return if we have no xchan here 2021-10-03 12:22:33 +00:00
Mario
58ee147653 fix typo 2021-10-03 08:20:16 +00:00
Mario
28ad6a6883 remove redundant query and exit with status 410 if channel was removed 2021-10-03 07:18:49 +00:00
Mario
9de8aefa98 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-03 07:11:27 +00:00
Mario
66c273ae8d channel_purge: raise limit by factor of 10 2021-10-03 07:11:12 +00:00
Mario Vavti
b27fbf209e Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-03 09:05:54 +02:00
Mario Vavti
4afd1ac705 add optional $removed argument to channelx_by functions to allow inclusion of removed channels which is required (mod channel, daemon notifier -> refresh_all) if a channel got removed also remove caching to App so we always get a fresh copy. In import_hublocs() add site_id to the array passed to Libzot::gethubs() because it is expected there. 2021-10-03 09:05:32 +02:00
Mario
d556ef59e6 sigh... 2021-10-02 14:09:55 +00:00
Mario
81e972b85c another try on pg test 2021-10-02 14:02:58 +00:00
Mario
3bb04cc323 nope - disable pg test until the issue is resolved 2021-10-02 13:28:35 +00:00
Mario
9ff43f081f another try to fix pg test 2021-10-02 13:23:44 +00:00
Mario
8c014e3b6b see if this fixes pgsql test issue 2021-10-02 13:15:17 +00:00
Mario
d8378a17c9 nav move header outsite of container - fixes app sticking above header when sorting 2021-10-02 13:04:10 +00:00
Mario
574a01727e fix removed channels counted for max id check and disable moving until we decide what to do with it 2021-10-02 12:56:35 +00:00
Mario
b5cea3301d cleanup api_auth and make it fetch the identity if we do not have it cached yet 2021-10-02 12:28:13 +00:00
Mario Vavti
9346a06f35 also check for vnotify 2021-10-01 22:48:09 +02:00
Mario Vavti
250e917c6e only show sse pubs if the app is installed 2021-10-01 22:44:26 +02:00
Mario Vavti
7b1cd37cd6 only bootstrap pubs if the app is installed 2021-10-01 22:30:00 +02:00
Mario Vavti
47e83a15c1 import_progress: deal with the situation where items/files are being imported but there are none to import 2021-10-01 21:52:30 +02:00
Mario
597e847a3b css fixes 2021-10-01 17:17:02 +00:00
Mario Vavti
47f3b41d5e remove redundant notice 2021-10-01 19:15:39 +02:00
Mario Vavti
e7f4c1ffd1 missing template class logic 2021-10-01 18:10:32 +02:00
Mario Vavti
9a87b8bf1b only allow resume if we are not completed yet 2021-10-01 17:24:19 +02:00
Mario Vavti
dac27aab68 remove logging 2021-10-01 17:11:14 +02:00
Mario Vavti
069a5429c9 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-01 17:09:54 +02:00
Mario Vavti
b1eaa810ce improve channel import progress page 2021-10-01 17:09:36 +02:00
Mario
e5e3c268a2 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-10-01 07:14:37 +00:00
Mario
22dff49673 improve file upload performance: start uploading next file only after the previous finished, make sure to not return when uploading via ajax 2021-10-01 07:14:05 +00:00
Max Kostikov
591905c282 Merge branch 'dev' into 'dev'
Fix possible storage conversion stuck on file save error

See merge request hubzilla/core!1988
2021-09-30 20:45:02 +00:00
Mario Vavti
6ed160e4fa wording 2021-09-30 17:50:36 +02:00
Mario Vavti
d462230b82 minor display change 2021-09-30 17:43:29 +02:00
Mario
e48ed9d06d Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-09-30 15:38:49 +00:00
Mario Vavti
6236869ebe implement file totals and add mod import_progress 2021-09-30 17:34:30 +02:00
Mario
2c7c9ae2d7 provide files total 2021-09-30 15:33:10 +00:00
Mario Vavti
b9b4e71f7d provide a very simple status page for content import 2021-09-30 12:25:03 +02:00
Mario Vavti
b0bf646d71 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-09-30 12:10:11 +02:00
Mario Vavti
5cb5ecdb54 implement channel purge daemon and send a notifier purge_all message if the xchan was deleted 2021-09-30 12:09:50 +02:00
Mario Vavti
44fa5ac9a1 add channel purge daemon 2021-09-30 12:06:28 +02:00
Max Kostikov
9a19f7eac9 Fix possible storage conversion stuck on file save error 2021-09-29 23:01:27 +02:00
Mario
af0896bb8b a possible fix for the nested list test 2021-09-29 20:57:16 +00:00
Mario
817237ef77 composer update league/html-to-markdown 2021-09-29 20:36:32 +00:00
Mario Vavti
fbefff6eed Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-09-29 21:47:36 +02:00
Mario Vavti
4ba47698d7 revise content import/export part 2 2021-09-29 21:47:12 +02:00
Mario
2688abf25a revise content import/export part 1 2021-09-29 19:43:22 +00:00
Mario
5eb79bd51e importer daemons: do not call with zap_compat flag and use return instead of kill so that queueworker can go on 2021-09-27 21:58:26 +00:00
Mario
d3f5f778a4 cleanup mod import and implement importer daemons ported from zap 2021-09-27 20:49:37 +02:00
Mario
3eeb2b0ee4 add importer daemons ported from zap 2021-09-27 18:37:09 +00:00
Mario
230a1919dd add outbox 2021-09-27 18:36:04 +00:00
Mario
14004fbf7f support un-starring of apps in app bin 2021-09-27 11:13:16 +00:00
Mario
73e8af98f2 fix notification panel collapsed state not saved if closed manually 2021-09-27 07:01:33 +00:00
Mario
0117a0019b make sure to also include ap hublocs here. we will select zot6 later in the function if present 2021-09-26 18:10:34 +00:00
Mario
35ff8781f0 always promote the outbox 2021-09-26 12:15:14 +00:00
Mario
2d17442f28 externals: if dealing with AP profiles also fetch comments. there is no way to fetch conversations later 2021-09-25 10:17:45 +00:00
Mario
5c179522bb bring back externals (slightly different approach), rename zotfeed to outbox for consistency wit AP naming. warning: this commit requires update of addons! 2021-09-25 09:03:16 +00:00
Mario
b35d95da52 dismiss deleted xchans in query 2021-09-25 08:47:39 +00:00
Mario
feca5afaa5 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-09-23 20:43:49 +00:00
Mario
9cb5274d30 add zot6 specific handling to onepoll 2021-09-23 20:43:37 +00:00
Mario Vavti
2870fd46da Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-09-23 21:54:12 +02:00
Mario Vavti
dff8ef91a6 implement the top option in items_fetch 2021-09-23 21:52:27 +02:00
Mario
0588975e37 Ãfix wrong variable name and streamline icon with unseen notifications icon 2021-09-23 14:59:40 +00:00
Mario
e0600b241a make sure we do not mix up likes on direct messages and commments on direct messages in notices 2021-09-23 12:45:55 +00:00
Mario
d19aa8fb3b make sure entries is initialized 2021-09-23 11:17:45 +00:00
Mario
989a4f3d49 add notices tab to HQ widget 2021-09-23 10:42:37 +00:00
Mario
2a2c4d3e9c fix bs regression 2021-09-23 08:50:44 +00:00
Mario
a451449766 Revert "composer update bootstrap to version 5.1.1"
This reverts commit 89e4006b2d.
2021-09-23 08:33:36 +00:00
Mario
3347fab105 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-09-22 16:16:50 +00:00
Mario
33a6c92629 version 2021-09-22 16:16:35 +00:00
Mario
0707d33493 bootstrap update fixes 2021-09-22 16:14:28 +00:00
Mario
89e4006b2d composer update bootstrap to version 5.1.1 2021-09-22 06:38:27 +00:00
Mario Vavti
4eb8921635 improve item_url_replace() - fixes #1507 2021-09-21 11:07:23 +02:00
Mario
26ac452c96 mod manage: do not query info which we do not use in the UI and probably should not due to performance considerations 2021-09-21 07:40:00 +00:00
Mario
7122e1522a perform profile sync after all the fields are updated otherwise we will sync outdated data 2021-09-21 07:33:02 +00:00
Mario
5497adfde6 add option to mark all notices of a thread read if a notice of the thread is clicked (default 1) and fix a php error in find_parent() if $act->obj is not an array 2021-09-18 18:06:32 +00:00
Mario
d4c2e50285 changelog and version 2021-09-16 09:50:08 +00:00
Mario
7ba58208f2 version 6.2.1 and changelog 2021-09-16 08:04:59 +00:00
Mario
cc83677711 Merge branch 'master' of https://framagit.org/hubzilla/core 2021-09-16 07:49:43 +00:00
Mario
c28cce1b54 Merge branch 'dev' 2021-09-16 07:48:13 +00:00
Mario
9052695a13 typo 2021-09-15 11:03:19 +00:00
Mario
46b8db53ab provide a get_cached_actor_provider hook and improve the author/owner handling in Libzot::import() 2021-09-15 10:59:16 +00:00
Mario
0b716b3cc7 fix $desturl set to wrong value (null) 2021-09-13 11:36:41 +00:00
Mario
d115e09abc do not process summary in cleanup_bbcode() fixes issue #1612 2021-09-12 17:54:20 +00:00
Mario
0f803aa3ae when updating the channel name from profiles make sure to lookup the xchan entry by xchan_hash since xchan_url is set to the primary location but we might be updating from a clone
(cherry picked from commit e5dc3c05df)
2021-09-10 14:34:21 +02:00
Mario
e5dc3c05df when updating the channel name from profiles make sure to lookup the xchan entry by xchan_hash since xchan_url is set to the primary location but we might be updating from a clone 2021-09-10 12:29:05 +00:00
Mario
1cfe5c3e16 fix spacing issue for collapsed pinned apps with an image
(cherry picked from commit e2d0269b5c)
2021-09-10 10:12:39 +02:00
Mario
e2d0269b5c fix spacing issue for collapsed pinned apps with an image 2021-09-10 08:11:19 +00:00
Mario
b95c61d2c2 fix language selector reloading the page if not clicking the icon exactly and bs5 modal issues
(cherry picked from commit 7b0f8f2896)
2021-09-08 21:50:25 +02:00
Mario
7b0f8f2896 fix language selector reloading the page if not clicking the icon exactly and bs5 modal issues 2021-09-08 19:48:42 +00:00
Mario
25a81ea500 update release date 2021-09-08 07:50:57 +00:00
Mario
4c5f0a05c7 Merge branch '6.2RC' 2021-09-08 07:43:40 +00:00
Mario
977a55eb84 version 6.2 2021-09-08 07:42:44 +00:00
Mario
8ec001c87b Merge branch 'dev' into 6.2RC 2021-09-07 10:22:07 +00:00
Mario
ddbc55d166 fix mod display regressions 2021-09-07 10:21:02 +00:00
Mario
9a3a0d94ea Merge branch 'dev' into 6.2RC 2021-09-07 09:29:14 +00:00
Mario
1d3a59e0cd resolve some vsprintf issues 2021-09-07 09:26:06 +00:00
Mario
ad7c84eda7 Merge branch 'dev' into 6.2RC 2021-09-07 07:36:53 +00:00
Mario
fe62b245ca update changelog 2021-09-07 07:34:59 +00:00
Mario
6084360588 deprecate the custom highlight [hl] bbcode in favor of [mark] which is a html5 standard 2021-09-07 07:33:36 +00:00
Mario
52995bde12 deprecate the custom highlight [hl] bbcode in favor of [mark] which is a html5 standard 2021-09-07 07:32:49 +00:00
Mario
0f54b26e9d bump version 2021-09-06 19:26:30 +00:00
Mario
2523ebc76a version 6.2RC1 2021-09-06 19:24:45 +00:00
Mario
c1ce211b56 Merge branch 'dev' into 6.2RC 2021-09-06 19:22:39 +00:00
Mario
1aa7826331 strings update 2021-09-06 19:22:04 +00:00
Mario
29a1556541 more changelog 2021-09-06 19:17:24 +00:00
Mario
93f48aa805 update changelog 2021-09-06 19:13:30 +00:00
Mario
95367a8267 if posting from hq return to the message we just posted 2021-09-06 10:19:37 +00:00
Mario
97ef781a0f fix post mail check in Activity::create_note() 2021-09-06 09:38:41 +00:00
Mario
81351d2952 update strings 2021-09-06 09:29:23 +00:00
Mario
8d28649e1b check the post_mail permission for direct messages 2021-09-06 09:10:19 +00:00
Mario
9495fef79b fix anon comments for cards and articles 2021-09-05 11:46:52 +00:00
Mario
de02d4c04b do not save collections in a separate xconfig anymore 2021-09-05 11:16:20 +00:00
Mario
18cd3926d7 omit deleted hublocs in get_actor_hublocs() and use Activity::get_actor_collections() to get collections. Fallback to xconfig->collections if Activity::get_actor_collections() does not return anything yet. 2021-09-05 11:11:51 +00:00
Mario
0e1e1cda7a fix regressions in mod hq 2021-09-04 20:18:59 +00:00
Mario
b3f2374b57 work around some weird regex interference 2021-09-04 19:46:17 +00:00
Mario
793881b9f9 more gen_link_id() 2021-09-04 08:30:04 +00:00
Mario
529824d010 more unpack_link_id() 2021-09-04 08:18:41 +00:00
Mario
c47e21f3a7 refactor actor_store and actor cache part 1 2021-09-04 07:37:49 +00:00
Mario
d83c013bec Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-09-04 07:36:28 +00:00
Mario
17220b2465 implement unpack_link_id() in mod channel 2021-09-04 07:34:09 +00:00
Mario
5dcf053b4c implement strict mode for base64url_decode() and introduce unpack_link_id() 2021-09-04 07:32:01 +00:00
Max Kostikov
a11fe8c6c6 Merge branch 'dev' into 'dev'
Update Russian translation

See merge request hubzilla/core!1987
2021-09-01 20:09:21 +00:00
Max Kostikov
70370407ad Fix index in Russian plurals 2021-09-01 22:05:50 +02:00
Max Kostikov
7973f11cd7 Fix Russian plurals 2021-09-01 22:02:20 +02:00
Max Kostikov
44371c9adf Update Russian translation 2021-09-01 21:36:16 +02:00
Mario
3d40ea7f44 version 2021-09-01 19:33:14 +00:00
Mario
8a3446c021 missing file 2021-09-01 19:31:09 +00:00
Mario
6a8cc313da bump version 2021-09-01 18:33:10 +00:00
Mario
7a1c72d5a4 composer dump autoload 2021-09-01 18:18:57 +00:00
Mario
4e7525c355 version and strings 2021-09-01 18:17:01 +00:00
Mario
e20a2752d6 add an optional force flag to actor_store() 2021-08-30 18:03:54 +00:00
Mario
e25558e24d improve icon lookup 2021-08-30 15:36:12 +00:00
Mario
ada7d4eef5 Merge branch 'owafix' into 'dev'
OWA: very difficult to trace failures due to empty public key record. The...

See merge request hubzilla/core!1986
2021-08-30 11:08:40 +00:00
Mario
3fb4077672 Merge branch 'photodir' into 'dev'
file is stored in wrong directory (/) if uploaded using photo module and it...

See merge request hubzilla/core!1985
2021-08-30 07:56:00 +00:00
Zot
5b73cee0d8 file is stored in wrong directory (/) if uploaded using photo module and it... 2021-08-30 07:56:00 +00:00
nobody
8343f63964 OWA: very difficult to trace failures due to empty public key record. The signature might succeed because an empty key triggers an external key fetch. But the empty key cannot encrypt the token. This has been observed in the wild on a number of sites/projects. 2021-08-29 04:54:50 -07:00
Mario
5532560d07 do not define colors in manifest (system colors are mostly the better fit) and use profile fullname instead of channel_name in nav 2021-08-29 10:51:44 +00:00
Mario
ed277dbda9 more app descriptions and remove some unused images 2021-08-28 17:57:06 +00:00
nobody
2866c0b173 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-08-28 01:09:11 -07:00
Mario
5eaabbdb18 slightly improve push notification handling for HQ and some app descriptions 2021-08-27 18:41:52 +00:00
Mario
d24fbb51fc adjust background color 2021-08-26 18:27:38 +00:00
Mario
6e4c9d684d port latest pwa work from zap 2021-08-26 18:03:17 +00:00
Mario
3ff184f8bb whitespace 2021-08-26 11:57:50 +00:00
Mario
a68b5f9de4 more app descriptions 2021-08-26 10:28:38 +00:00
Mario
d5bf42faf0 Merge branch 'dev' into 'dev'
issue 1599

See merge request hubzilla/core!1984
2021-08-26 08:38:42 +00:00
Zot
88b13658a7 issue 1599 2021-08-26 08:38:41 +00:00
nobody
05152ac8c8 issue 1599 - import_author_zot failing if primary is both dead and unknown 2021-08-25 19:15:46 -07:00
nobody
aa2106f949 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-08-25 19:13:31 -07:00
Mario
6261d0826c db update 1248 to clean up possible bogus entries in xconfig and remove gnusoc from app 2021-08-25 15:54:26 +00:00
Mario
2e7a915ee8 add appstore widget to appman 2021-08-25 10:19:20 +00:00
Mario
0081bafab2 more app descriptions 2021-08-25 08:56:34 +00:00
Mario
64b59b4358 capitalize widget titles 2021-08-25 06:56:45 +00:00
Mario
19f9bbcad4 nav: fix minor display issue and add some code duplication for better readability 2021-08-25 06:37:14 +00:00
Mario
f399528055 more app descriptions and change the image counter to display % of images loaded instead of loaded images count 2021-08-24 18:50:19 +00:00
Mario
fea3980c01 channel manager -> channels 2021-08-24 09:03:09 +00:00
Mario
8804499cb7 channel_menu is not used anymore 2021-08-24 08:41:02 +00:00
Mario
fa1878fda1 nav cleanup 2021-08-24 08:37:51 +00:00
Mario
b129d74a38 affinity needs a version bump to pick up the description 2021-08-23 11:42:53 +00:00
Mario
189da4fdc1 untangle the app template into separate templates and fix bbcode view 2021-08-23 10:32:48 +00:00
Mario
824894baf0 more app descriptions and return to the app if installed from the module itself 2021-08-23 07:59:37 +00:00
Mario
2bd4f7384e more app descriptions 2021-08-22 18:56:04 +00:00
Mario
1c44b37cb0 rename variable 2021-08-22 18:14:16 +00:00
Mario
ab0da7db13 use the slightly altered app_render() function instead of a separate function 2021-08-22 17:55:38 +00:00
Mario
052633d570 improve documentation 2021-08-22 10:13:25 +00:00
Mario
3bb71a6ba8 infrastructure to provide an app install widget for modules and make the bookmark app use it 2021-08-22 09:20:40 +00:00
Mario
7093b66b76 fix typo 2021-08-21 08:30:13 +00:00
Mario
168010a32c remove deprecated forum term type and re-introduce bookmark term type 2021-08-21 08:26:46 +00:00
Mario
6eb84a3d9a restructure apps to make space for app descritions 2021-08-21 08:25:15 +00:00
Mario
69d909596a only redirect to hq if local 2021-08-17 18:37:19 +00:00
Mario
dd296e1aaa more legacy mail cleanup - issue #1595 2021-08-17 18:18:52 +00:00
Mario
c3bbc35e84 more bs5 fixes 2021-08-17 18:07:30 +00:00
Mario
952407363e make sure we have a path before running getimagesize() on it
(cherry picked from commit a2403042c2)
2021-08-17 09:59:03 +02:00
Mario
2deb75de8d remove redundant closing div tag
(cherry picked from commit 87cf2039ad)
2021-08-17 09:58:42 +02:00
Mario
a2403042c2 make sure we have a path before running getimagesize() on it 2021-08-17 07:53:07 +00:00
Mario
87cf2039ad remove redundant closing div tag 2021-08-16 19:36:47 +00:00
Mario
db4109c2a0 streamline default link color 2021-08-15 08:26:11 +00:00
Mario
36564b5aa7 bump version 2021-08-04 14:47:52 +00:00
Mario
101fc33c63 bs5 sets scroll-behavior to smooth which does weird things especially on mobile devices - unset it 2021-08-04 14:46:46 +00:00
Mario
bd2270deb6 app-bin-ng: add a link to the bin for convenience and use the traditional ajax call instead of the post shortcut 2021-08-04 14:13:28 +00:00
Mario
5b72f6f09d fix another bs5 regression 2021-08-04 12:36:20 +00:00
Mario
ee1cec8de2 the default 400px is slightly overkill 2021-08-03 07:35:43 +00:00
Mario
b0a499d8b1 remove logging 2021-08-03 07:17:55 +00:00
Mario
08f70c49f8 Merge branch 'app-bin-ng' into 'dev'
Apps drag and drop feature

See merge request hubzilla/core!1982
2021-08-03 07:12:36 +00:00
Mario
cddc021772 Apps drag and drop feature 2021-08-03 07:12:35 +00:00
Mario
571bae9d1c Merge branch 'ab-dev' into 'dev'
Updated Polish GUI translation

See merge request hubzilla/core!1981
2021-08-03 07:05:45 +00:00
Andrzej Budziński
e01666526e Updated Polish GUI translation according to changes made in version 6.0
/ 6.1 Hubzilla + stylistic fixes and typos.
2021-08-01 03:41:24 +02:00
Mario
562a160a52 remove another possible source for hubloc confusion 2021-07-29 12:29:39 +00:00
Mario
cb57c4ea18 Merge branch 'bs5' into 'dev'
Update to bootstrap 5 and implement next generation app menu (work in progress)

See merge request hubzilla/core!1980
2021-07-29 09:31:47 +00:00
Mario
b7ffec6fbe bs5 border fix 2021-07-29 09:15:18 +00:00
Mario
94be9f115b another badge fix 2021-07-29 09:06:02 +00:00
Mario
693736df7c dropdown-menu-right -> dropdown-menu-end 2021-07-29 09:03:22 +00:00
Mario
943e7dd242 fix notification button class 2021-07-29 08:45:42 +00:00
Mario
c1526b473b bump version 2021-07-29 08:34:33 +00:00
Mario
d459dfac74 update to bootstrap 5.0.2 2021-07-29 08:25:05 +00:00
Mario
cec2f0d894 more work on bs5 2021-07-29 08:19:33 +00:00
Mario
9722d157bf Merge branch 'dev' into bs5 2021-07-29 06:59:13 +00:00
Mario
6bcd24ab90 check if isset before unsetting to omit php errors
(cherry picked from commit c6133d2558)
2021-07-27 21:12:59 +02:00
Mario
c6133d2558 check if isset before unsetting to omit php errors 2021-07-27 19:07:09 +00:00
Mario
ea8d38dec0 version 6.0.1 2021-07-27 07:12:59 +00:00
Mario
0fa41f082d Merge branch 'dev' 2021-07-27 07:11:12 +00:00
Mario
83b1f62e13 more changelog 2021-07-27 07:10:43 +00:00
Mario
b19213b60b Merge branch 'dev' 2021-07-27 07:07:53 +00:00
Mario
3c5b18913f changelog 2021-07-27 07:06:22 +00:00
Mario Vavti
676a65cd61 notifications: move handlers out of jquery ready function otherwise they might not fire on pageload 2021-07-17 14:00:03 +02:00
Mario Vavti
95fb66b433 code style 2021-07-16 13:53:32 +02:00
Mario Vavti
a57529bc54 bump min version 2021-07-16 13:50:38 +02:00
Mario Vavti
4f15c08805 more work on moving notifications handling from main.js to the notifications widget 2021-07-16 13:48:35 +02:00
Mario Vavti
7b2f4b0814 fix a regression in regard to unified session page load times intoduced in 6.0 2021-07-16 12:56:57 +02:00
Mario Vavti
3051e2c268 redirect to the local item instead of the item at the primary location if we deal with a wall item 2021-07-16 12:04:31 +02:00
Mario
d7489e3913 Merge branch 'dev' into 'dev'
Fix link to source on clones

See merge request hubzilla/core!1975
2021-07-16 09:46:08 +00:00
Mario Vavti
62606bf006 photo upload: always show the textarea so that text and tags can be added even if no status post is sent 2021-07-16 11:42:54 +02:00
Max Kostikov
c68f2bc2d1 Fix link to source on clones 2021-07-16 11:12:32 +02:00
Mario Vavti
f5669c9935 chanview: dismiss xchans which are marked deleted 2021-07-15 12:07:54 +02:00
Mario Vavti
9e2bdb012e fix release date 2021-07-09 12:02:50 +02:00
Mario Vavti
d8ac25c35a version 6.0 2021-07-09 11:33:19 +02:00
Mario Vavti
2dd47a9f59 Merge branch '6.0RC' 2021-07-09 11:31:26 +02:00
Mario Vavti
a92ad512bb Merge branch 'dev' into 6.0RC 2021-07-08 13:36:06 +02:00
Mario Vavti
e39b29cc4b set touch_max to 1/10 of the screen width to prevent overlaping with cursor positioning 2021-07-08 13:35:28 +02:00
Mario
76ed9f3915 typo 2021-07-08 13:23:49 +02:00
nobody
73b53675b1 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-07-06 05:02:52 -07:00
Mario Vavti
fd6ec17d4b version rc1 2021-07-05 10:55:10 +02:00
Mario Vavti
8de364c83e Merge branch 'dev' into 6.0RC 2021-07-05 10:54:29 +02:00
Mario Vavti
9b9ac5054f changelog 2021-07-05 10:54:03 +02:00
Mario Vavti
9efea4e188 Merge branch 'dev' into 6.0RC 2021-07-05 10:51:31 +02:00
Mario Vavti
d45df824ed redbasic: close left aside if hq control button is clicked 2021-07-05 10:42:36 +02:00
Mario Vavti
50ead82bc4 remove redundant z-index 2021-07-04 14:05:48 +02:00
Mario Vavti
c43f501716 ux fixes 2021-07-04 13:57:20 +02:00
Mario Vavti
86d471834e do not call stickyScroll() on small screens - it is not functional 2021-07-03 14:52:00 +02:00
Mario Vavti
a1f7f7a966 since position sticky has no effect if overflow is hidden and the workarounds also have issues, we will automatically scroll to top when left aside is brought in 2021-07-03 14:36:27 +02:00
Mario Vavti
081d82218b implement a very simple swipe mechanism for bringing in left aside 2021-07-03 14:27:55 +02:00
Mario Vavti
cca3eb8c56 work around the fact that sticky does not stick if a parent element has set overflow to hidden 2021-07-02 17:49:03 +02:00
Mario Vavti
933c097a52 changelog typos 2021-07-02 16:46:49 +02:00
Mario Vavti
f5912e05ef do not use summary in photo object 2021-07-02 16:37:50 +02:00
Mario Vavti
e94eb1af0c remove mail and conv tables from install SQL schemas 2021-07-02 16:13:48 +02:00
Mario Vavti
0ab7996a2a update changelog 2021-07-02 16:07:31 +02:00
Mario
faeec0b77b revert ebc84eab3f instead be more picky about the xchan in handle_tag() 2021-07-02 07:23:18 +00:00
Mario Vavti
ebc84eab3f update by xchan_url to catch all associated entries 2021-07-01 22:30:29 +02:00
Mario
b560b6fbd3 Merge branch 'dev' into 6.0RC 2021-07-01 09:27:14 +00:00
Mario
c6b3bc5b20 redbasic: bump version limits 2021-07-01 09:26:20 +00:00
Mario
e31cb28b08 Merge branch 'dev' into 6.0RC 2021-07-01 07:44:51 +00:00
Mario
458fa7bfeb port fixes from as_actor_store() 2021-06-30 19:04:42 +00:00
Mario
fab3f0f2de fix RC version after last merge 2021-06-30 12:06:55 +00:00
Mario
c8d9238c58 missing composer file 2021-06-30 09:11:07 +00:00
Mario
5aa79caf84 bump dev version to 6.1 2021-06-30 07:25:23 +00:00
Mario
12cabbde9e update sbom 2021-06-30 07:19:38 +00:00
Mario
ca3ab2014f update composer autoload 2021-06-30 07:19:16 +00:00
Mario
3e6283a262 strings update 2021-06-30 07:11:44 +00:00
Mario
bc0d0a6b39 version 6.0RC 2021-06-30 07:07:58 +00:00
Mario
6a4727e3eb fix variable name 2021-06-29 18:21:12 +00:00
Mario
ff6d1c808d version 2021-06-29 09:54:13 +00:00
Mario
197d15b7de only remove elements after the delete has happened 2021-06-29 09:53:40 +00:00
Mario
bb5f6a1d79 tools -> features 2021-06-29 09:40:34 +00:00
Mario
e8c6121b4e version 2021-06-29 09:24:13 +00:00
Mario
bed81d785c an attempt to improve the query for direct messages on some systems with hopefully no bad side-effect for others 2021-06-29 09:22:38 +00:00
Mario
0503914527 fix deleting and starring in unthreaded view 2021-06-29 08:45:48 +00:00
Mario
cb65ae6848 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-06-29 07:49:34 +00:00
Mario
652d083766 implement removing of notifications/preview-messages of deleted items 2021-06-29 07:49:19 +00:00
Mario
091d9c10fb Merge branch 'clean-up' into 'dev'
mod network clean-up

See merge request hubzilla/core!1974
2021-06-29 07:15:44 +00:00
Xanthor
835fe10bfe mod network clean-up 2021-06-29 07:15:42 +00:00
Mario
5a474f94e0 fix query logic 2021-06-29 05:45:05 +00:00
Mario
d322feeb54 more deprecate legacy zot 2021-06-28 08:37:05 +00:00
Mario
842c7b31fb Merge branch 'fix' into 'dev'
fix call to prepare_body

See merge request hubzilla/core!1973
2021-06-28 06:55:47 +00:00
Michael Johnston
1034f02d4d fix call to prepare_body 2021-06-28 06:55:47 +00:00
Mario
3f6b6dfaf3 fix regression in relation with recent photo changes 2021-06-27 15:20:06 +00:00
Mario
d3d4dee36a version 2021-06-27 13:57:57 +00:00
Mario
7002248325 update 1247 to clean up bogus entries in updates. this only affects directory servers. 2021-06-27 13:57:18 +00:00
Mario
d8d0f01f80 bump version 2021-06-27 13:46:10 +00:00
Mario
b3b842c071 update 1246 to flag legacy zot hublocs and xchans deleted. we will set the deleted flag to 2 so we can distinguish them from real deletes if necessary 2021-06-27 13:45:06 +00:00
Mario
aca8d1b8f9 bump version 2021-06-25 11:00:36 +00:00
Mario
4f328740dc more work on notifications 2021-06-25 10:53:37 +00:00
Mario Vavti
2f1c2f42b1 check if empty 2021-06-25 08:47:05 +02:00
Mario
d42a998e49 strip html tags from notification message 2021-06-25 06:24:46 +00:00
Mario
167db22e15 slightly refactor for desktop notifications and fix minor issues 2021-06-24 19:31:19 +00:00
Mario
108777251e some preperatory work on desktop notifications 2021-06-24 11:27:51 +00:00
Mario
088713a555 Notification.requestPermission() only fires if wraped in click handler 2021-06-24 08:15:44 +00:00
Mario
7582ebc9c8 remove deprecated dir and queue fns 2021-06-24 07:08:12 +00:00
Mario Vavti
97d9764f01 if there are no messages display that there are no messages 2021-06-23 22:14:01 +02:00
Mario Vavti
dfcd8395d5 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-06-23 21:15:26 +02:00
Mario
6e91bee0ba some work on streamlining mod photos 2021-06-23 15:52:04 +00:00
Mario Vavti
cf791a1909 libzotdir: make sure we have the relevant data before string into updates 2021-06-23 17:09:45 +02:00
Mario
c6d872d177 jot: do not collapse the form if in popup mode 2021-06-23 07:39:20 +00:00
Mario
cc4f3a827c streamline jot popup for mod hq 2021-06-21 18:45:33 +00:00
Mario
0489fbb685 theme: slightly more transparency for the backdrop 2021-06-21 18:21:19 +00:00
Mario
7da23603ec fiÃlter children by tt-filter-active class instead of visibility selector to omit reload loop in mobile view where notifications ar not visible while off-canvas 2021-06-21 18:07:19 +00:00
Mario
afb4ae2109 Merge branch 'dev' into 'dev'
Clean up Search.php & Enotify.php code

See merge request hubzilla/core!1972
2021-06-21 17:42:57 +00:00
Xanthor
e024375b15 Clean up Search.php & Enotify.php code 2021-06-21 17:42:56 +00:00
Mario
3632fb359f calendar: emit a warning if the calendar for the created event is disabled 2021-06-21 07:52:47 +00:00
Mario
2a3ba5d5f0 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-06-20 08:25:41 +00:00
Mario
5b9dc764c5 make sure to not calculate timeago before the translations are loaded 2021-06-20 08:25:29 +00:00
Max Kostikov
24a0d4f308 Merge branch 'dev' into 'dev'
Update Russian translation

See merge request hubzilla/core!1970
2021-06-19 18:06:49 +00:00
Max Kostikov
88f5b10b22 Update Russian translation 2021-06-19 20:00:52 +02:00
Mario
cf69859885 one more place to drop media 2021-06-18 10:12:08 +00:00
Mario
af71f7f8cd remove notes from network pdl - it is now located in HQ 2021-06-18 10:06:42 +00:00
Mario
ec22ca7553 css and js fixes 2021-06-18 09:58:00 +00:00
Mario
c42d8a81c7 bbcode: add option to drop media content 2021-06-18 09:51:20 +00:00
Mario
0e7473c3ba more css improvements 2021-06-18 08:59:22 +00:00
Mario
f4f9ccc3b2 css fixes 2021-06-18 08:55:49 +00:00
nobody
efda8aac1d Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-06-17 14:57:47 -07:00
Mario
a84cec4acd fix wrong class and bump version 2021-06-17 12:21:39 +00:00
Mario
cf6b7a4236 whitespace 2021-06-17 12:13:40 +00:00
Mario
998f46b45c update hq_controls widget pdl 2021-06-17 12:12:50 +00:00
Mario
5ca352a6c3 allow to add a wrapper class to the hq_controls widget 2021-06-17 12:10:54 +00:00
Mario
a34bd3b013 fix issue where notifications were not loaded if a filter was applied 2021-06-17 11:21:59 +00:00
Mario
c268bc327a fix issues with browser back button and minor cleanup 2021-06-17 10:14:23 +00:00
Mario
e79a27c654 just use ... as preview if we could not wind anything useful 2021-06-17 08:08:14 +00:00
Mario
2f0bac8ddf consolidate notifications strings 2021-06-17 08:06:26 +00:00
Mario
12d7d1c3f0 fix wrong variable 2021-06-17 07:50:16 +00:00
Mario
34ca2cddd4 only show notes if the app is enabled 2021-06-17 07:43:32 +00:00
Mario
fa076efd3b Merge branch 'dm' into 'dev'
New landing page HQ with separate views for direct messages, public/limited messages and starred messages if the feature is enabled

See merge request hubzilla/core!1969
2021-06-17 07:33:46 +00:00
Mario
b55676d089 New landing page HQ with separate views for direct messages, public/limited messages and starred messages if the feature is enabled 2021-06-17 07:33:45 +00:00
Mario
9b71c090c5 Merge branch 'translation-pl' into 'dev'
Translation pl - generated new util/hmessages.po, translated new strings + few fixes

See merge request hubzilla/core!1968
2021-06-17 07:33:15 +00:00
Mario
0f8e4e4eed Merge branch 'dev' into 'dev'
Fix email local part validation

See merge request hubzilla/core!1967
2021-06-17 07:30:57 +00:00
Andrzej Budziński
de1e3d7b17 Polish translation: fixes 2021-06-13 02:30:27 +02:00
Andrzej Budziński
3d077a0bc6 Generated new util/hmesages.po + new Polish translations 2021-06-12 03:16:09 +02:00
Andrzej Budziński
c74d1f4bf7 Polish translation: a little fixes 2021-06-10 23:47:27 +02:00
Andrzej Budziński
776e1211bc fixes in .gitignore file 2021-06-10 23:39:22 +02:00
Max Kostikov
b5a8ca6ef7 Merge branch 'translation-pl' into 'dev'
Polish translation: some fixes

See merge request hubzilla/core!1966
2021-06-10 08:11:20 +00:00
Max Kostikov
2c198ed89a Remove unnecessary parentheses 2021-06-09 12:53:55 +02:00
Max Kostikov
17fdeb9e1f Fix email local part validation 2021-06-09 11:06:12 +02:00
Mario Vavti
e41858f57c remove redundant arg 2021-06-09 09:45:25 +02:00
Mario
219d47f04c bs5: more fixes 2021-06-07 18:38:54 +00:00
Mario
750721c1a0 bs5: minor fix 2021-06-07 14:12:30 +00:00
Mario
b66b43256b bs5: more notifications fixes 2021-06-07 13:21:44 +00:00
Mario
58cacaff06 bs5: more notifications work 2021-06-07 12:37:12 +00:00
Mario
9aebb01d62 bs5: notifications work 2021-06-07 14:10:57 +02:00
Mario
f3b4308cb5 upgrade to bootstrap 5.0.1 and first batch of fixes 2021-06-07 12:56:27 +02:00
Andrzej Budziński
12089e127a Polish Translation: a little fixes 2021-06-05 21:37:29 +02:00
Andrzej Budziński
c75b8711b1 Polish Translation: a little fixes 2021-06-05 20:43:49 +02:00
Mario
67322c1264 more work on directory sync 2021-06-05 18:40:23 +00:00
Mario
607f0346f4 version 2021-06-05 10:14:08 +00:00
Mario
d5bb34f65d composer update symfony/polyfill-ctype 2021-06-05 09:42:45 +00:00
Mario
3e18efd89f composer update psr/log 2021-06-05 09:38:58 +00:00
Mario
bec3cb48e5 composer update commerceguys/intl to version 1.1.0 2021-06-05 09:34:18 +00:00
Mario
e8d2819c42 fix test 2021-06-05 09:17:51 +00:00
Mario
cc85c2f4d7 composer update commerceguys/intl 2021-06-05 09:11:39 +00:00
Mario
bee4fa9937 missing use statement 2021-06-05 09:06:09 +00:00
Mario
14ab5801d2 league/html-to-markdown suports tables now 2021-06-05 08:55:32 +00:00
Mario
fd8a5ff4c4 composer update league/html-to-markdown 2021-06-05 08:47:24 +00:00
Andrzej Budziński
ef9ae0db94 Polish translation: some fixes 2021-06-05 10:45:09 +02:00
Mario
4db384da34 composer update smarty 2021-06-05 08:32:34 +00:00
Mario
0784d2ea4e Merge branch 'dev' into six 2021-06-05 07:52:43 +00:00
Mario
b90db6931d Merge branch 'dev' into 'dev'
Changed behavior in the user interaction of the languages selection. Now works...

See merge request hubzilla/core!1952
2021-06-05 07:51:38 +00:00
Hilmar Runge
25497336bb Changed behavior in the user interaction of the languages selection. Now works... 2021-06-05 07:51:38 +00:00
Mario
a0ee9557f0 Merge branch 'translation-pl' into 'dev'
The Polish translation: ixes and new doc translation

See merge request hubzilla/core!1965
2021-06-05 07:50:50 +00:00
Mario
7b3eb09067 Merge branch 'dev' into six 2021-06-05 07:48:44 +00:00
Andrzej Budziński
1fc3be0c9f Polish translation:
Final fixes in 'view/pl/hmessages.po' + 'docs/pl'.
The Polish translation of Habzill's and Zap's GUI is consistent.
The most important articles of the documentation are also translated
Quality improvements to the documentation remain to be made, including the writing of new articles
(guides).
2021-06-04 23:35:49 +02:00
Mario
6de327402b version 5.6.1 2021-06-04 11:27:09 +02:00
Mario
131ce826c3 Merge branch 'dev' 2021-06-04 11:10:37 +02:00
Mario
a3f4ad9ea0 fix es plural return 2021-06-04 11:10:14 +02:00
Mario
ec3b1131d9 changelog 2021-06-04 11:08:55 +02:00
Mario
74c0345009 Merge branch 'dev' 2021-06-04 10:26:17 +02:00
Mario
628b03da29 fix css issue 2021-06-04 10:25:36 +02:00
Mario
bd59fb0b4e Merge branch 'dev' 2021-06-04 10:09:22 +02:00
mjfriaza
443b436be8 Update Spanish
(cherry picked from commit 993d648011)
2021-06-04 07:52:45 +00:00
mjfriaza
993d648011 Update Spanish 2021-06-04 07:51:53 +00:00
Mario
343f3059e6 fix login name label for the case when system.verify_email is disabled
(cherry picked from commit e44bf42c64)
2021-06-04 07:48:25 +00:00
Mario
10f8fe8973 use uuid for hash 2021-06-04 07:46:36 +00:00
Mario
e44bf42c64 fix login name label for the case when system.verify_email is disabled 2021-06-04 07:45:33 +00:00
Mario
3d1684fa94 Revert "fix login name label for the case when system.verify_email is disabled"
This reverts commit d882bad706.
2021-06-04 07:44:37 +00:00
Mario
d882bad706 fix login name label for the case when system.verify_email is disabled 2021-06-04 07:43:23 +00:00
nobody
686530c187 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-06-03 16:01:16 -07:00
Mario Vavti
e5c8273f72 Merge branch 'six' of https://framagit.org/hubzilla/core into six 2021-06-03 11:00:39 +02:00
Mario Vavti
440f7bacd6 directory improvements 2021-06-03 10:59:12 +02:00
Mario
ba22d3e9b6 fix issue where a deleted channel will return 404 before returning zotinfo
(cherry picked from commit 33463152e8)
2021-06-02 18:13:48 +00:00
Mario
33463152e8 fix issue where a deleted channel will return 404 before returning zotinfo 2021-06-02 17:58:46 +00:00
Mario
657af3024e Merge branch 'dev' into 'dev'
Make pubstream ordering configurable

See merge request hubzilla/core!1964
2021-06-02 08:33:55 +00:00
Max Kostikov
7d82a34538 Make pubstream ordering configurable 2021-06-02 08:33:54 +00:00
Mario
a0b788e96a fix article summary duplicated when editing - issue #1577
(cherry picked from commit 50c14d353b)
2021-06-02 08:32:41 +00:00
Mario
50c14d353b fix article summary duplicated when editing - issue #1577 2021-06-02 08:31:43 +00:00
Mario Vavti
b63aa3079b fix regression where authors from non zot6, activitypub networks got dismissed (e.g. relayed diaspora comments)
(cherry picked from commit b3df15a3c6)
2021-06-02 07:52:40 +00:00
Mario
25be24e6b8 Merge branch 'six' of https://framagit.org/hubzilla/core into six 2021-06-02 07:44:36 +00:00
Mario Vavti
2ec2da5dff Merge branch 'six' of https://framagit.org/hubzilla/core into six 2021-06-02 09:42:27 +02:00
Mario Vavti
b3df15a3c6 fix regression where authors from non zot6, activitypub networks got dismissed (e.g. relayed diaspora comments) 2021-06-02 09:41:57 +02:00
nobody
462980c70a Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-05-31 14:36:14 -07:00
Max Kostikov
2171686284 Merge branch 'translation-pl' into 'dev'
New traslations: view/pl/invite* files + some fixes

See merge request hubzilla/core!1963
2021-05-31 18:29:38 +00:00
Andrzej Budziński
b382edc61d Fixes to docs/pl/about/about.bb 2021-05-31 18:07:16 +02:00
Andrzej Budziński
5ae21d04b0 New traslations: view/pl/invite* files + some fixes 2021-05-31 13:39:11 +02:00
Mario
b0825ead84 Merge branch 'dev' into six 2021-05-31 11:33:47 +00:00
Mario
2980f852aa fix admin button state not displayed correctly
(cherry picked from commit baabb3a873)
2021-05-31 11:32:09 +00:00
Mario
5e07ebe7fa fix registration bug - issue #1574 2021-05-31 09:07:50 +00:00
Mario
baabb3a873 fix admin button state not displayed correctly 2021-05-31 10:14:26 +02:00
Mario
5ee1c3f2c8 include items.php in boot since it is required almost everywhere 2021-05-31 10:03:34 +02:00
Mario
3fe2a2b181 do not overwrite the original rawmsg iconfig that came with the item 2021-05-31 07:12:36 +00:00
Mario
3d2b923102 notifier fixes 2021-05-29 06:20:28 +00:00
Mario
43c941d370 fix notifier for non-zot hublocs 2021-05-28 20:15:34 +00:00
Mario
e1721b8496 remove masto hack - it does not make sense in threaded view 2021-05-28 20:14:15 +00:00
Mario
ccf3ed185f remove mod ping 2021-05-28 17:18:03 +00:00
Mario
99af27770e Merge branch 'dev' into six 2021-05-28 10:16:34 +00:00
Mario
e9088bd52e notifications: if we have to return early, make sure to set offset to -1 to prevent looping
(cherry picked from commit f72b8ce30f)
2021-05-28 10:13:25 +00:00
Mario
f72b8ce30f notifications: if we have to return early, make sure to set offset to -1 to prevent looping 2021-05-28 10:02:05 +00:00
Mario
19bb96121b move mark notifications read code to mod notifications 2021-05-28 09:58:18 +00:00
Mario
69ef7cf168 remove more mail leftovers 2021-05-28 08:42:08 +00:00
Mario
f1aace5a22 remove unobscure() 2021-05-28 08:28:32 +00:00
Mario
0718ac514d remove deprecated mail code 2021-05-28 08:11:40 +00:00
Mario
d289994da4 missing include 2021-05-28 07:22:49 +00:00
Mario
30f258b3f9 add check for type 2021-05-28 07:19:49 +00:00
Mario
d06d22c7c9 bump version 2021-05-27 20:06:22 +00:00
Mario
57c301d59c composer dump autoload 2021-05-27 19:58:34 +00:00
Mario
4bde2f64bd remove zot 2021-05-27 19:55:06 +00:00
Mario
8ca487115f remove include/msglib 2021-05-27 19:50:53 +00:00
Mario
7ad0a1e557 remove include/message (the file) 2021-05-27 19:50:35 +00:00
Mario
1aa626f0e8 remove include/message 2021-05-27 19:49:44 +00:00
Mario
7e36d17135 remove include/zot 2021-05-27 19:48:19 +00:00
Mario
2f7e875eb4 remove mod post 2021-05-27 19:45:34 +00:00
Mario
3ab8632d3b update mail widgets to not require include message and minor fixes 2021-05-27 19:20:07 +00:00
Mario
190fc4e3c4 fix typo 2021-05-27 17:44:24 +00:00
Mario
3eb1b9d168 remove reply_message_request(), implement force_refresh and minor fixes 2021-05-27 17:42:28 +00:00
Mario
2fb3d6ddf5 remove zot6/finger 2021-05-27 15:40:28 +00:00
Mario
bf74a75303 bump version 2021-05-27 12:25:23 +00:00
Mario
7d1b240954 fix typo 2021-05-27 12:07:29 +00:00
Mario
2db3e4ca48 fix test 2021-05-27 11:49:09 +00:00
Mario
cee2e63278 fix typo 2021-05-27 11:30:27 +00:00
Mario
9d5732400f remove mod message 2021-05-27 11:21:30 +00:00
Mario
3cb0613d04 mising use statement 2021-05-27 11:16:29 +00:00
Mario
d9920fce3a missing include 2021-05-27 11:10:09 +00:00
Mario
2765a0a9fd missing includes 2021-05-27 10:50:53 +00:00
Max Kostikov
92ea7fcfb1 Merge branch 'translation-pl' into 'dev'
Next fixes to Polish translation

See merge request hubzilla/core!1962
2021-05-27 10:05:30 +00:00
Mario
9d96793e1a update fresh 2021-05-27 09:48:50 +00:00
Mario
7776283a47 remove zot includes 2021-05-27 09:45:39 +00:00
Mario
c9d4802bf1 Ãremove queue_fn includes 2021-05-27 09:33:22 +00:00
Mario
37558e24f8 remove dir_fns includes 2021-05-27 09:30:57 +00:00
Mario
67cf9f6caf deprecate find_upstream_directory() 2021-05-27 09:22:38 +00:00
Mario
16146af039 deprecate remove_queue_by_posturl() 2021-05-27 09:18:46 +00:00
Mario
6a7e06f11c deprecate get_rpost_path() 2021-05-27 09:09:52 +00:00
Mario
adba56a5e5 remove mod events 2021-05-27 08:55:52 +00:00
Mario
90c9fc5338 deprecate import_xchan() 2021-05-27 08:39:23 +00:00
Mario
0a09f507fc remove zping 2021-05-27 08:30:00 +00:00
Mario
9ea60ba79f deprecate make_xchan_hash() 2021-05-27 08:27:33 +00:00
Mario
43ef82aaaa remove zfinger 2021-05-27 08:19:22 +00:00
Mario
7171d790f4 import Lib/Queue as LibQueue 2021-05-27 08:02:54 +00:00
Mario
4099549609 remove deprecated rating code 2021-05-27 07:58:56 +00:00
Mario
4e4bffe5c5 deprecate queue_deliver() 2021-05-27 07:52:18 +00:00
Mario
1c8000d026 remove more legacy zot quirks 2021-05-26 19:02:13 +00:00
Mario
ff34a787c3 php8: more id3 parser fixes 2021-05-26 18:02:29 +00:00
Mario
84c5f57d22 php8: more id3 parser fixes 2021-05-26 17:54:07 +00:00
Andrzej Budziński
64181c7cf1 Next fixes. It already looks very nice, but it's not end work yet for
this translation.
2021-05-26 17:15:09 +02:00
Mario
3c5f840cf0 typo 2021-05-26 12:29:15 +00:00
Mario
1fa4bc9ac0 remove most legacy zot quirks 2021-05-26 12:18:59 +00:00
Mario
b742910107 remove legacy zot from supported protocols 2021-05-26 11:28:33 +00:00
Mario
b7f124072f import_author_xchan(): do not import legacy zot 2021-05-26 11:25:36 +00:00
Mario
ec02eda113 handle_tag(): only use xchans with xhchan_deleted = 0 2021-05-26 09:36:13 +00:00
Mario
8d8523684c more id3parser 2021-05-26 08:51:35 +00:00
Max Kostikov
8a0c7b3fe1 Merge branch 'translation-pl' into 'dev'
Updating translatons strings + fixes to Polish translation

See merge request hubzilla/core!1961
2021-05-25 15:01:33 +00:00
Mario
a29dbaba21 disable mod post for now 2021-05-25 12:17:45 +00:00
Mario
51ad4fac01 php8: even even more fix unmaintained id3 parser 2021-05-25 12:08:58 +00:00
Mario
d863ba1b2a syntax error 2021-05-25 12:04:32 +00:00
Mario
175001eccd php8: even more fix unmaintained id3 parser 2021-05-25 11:47:26 +00:00
Mario
846d99cfce php8: more fix unmaintained id3 parser 2021-05-25 11:24:16 +00:00
Mario
2486a9c914 php8: fix un maintained id3 parser 2021-05-25 11:15:22 +00:00
Mario
a47a81db6f more notifier work 2021-05-25 11:13:13 +00:00
Andrzej Budziński
587e790892 Regenerating hstrings.ph file 2021-05-24 18:37:53 +02:00
Andrzej Budziński
f73a83aa55 Next fixes and generating new hstrings.php file 2021-05-24 17:18:13 +02:00
Andrzej Budziński
513cf2b8e2 Updating translation strings (v. 5.7) + fixes to Polish translation 2021-05-23 23:51:27 +02:00
Mario
ea215697ed remove location command from notifier 2021-05-23 20:36:00 +00:00
Mario
d40686e5d0 remove request command from notifier 2021-05-23 20:31:03 +00:00
Mario
0b7d343c7c remove mail and some hubzilla < 5.0 quirks from notifier 2021-05-23 20:10:43 +00:00
Mario
d692ed634a some cleanup 2021-05-23 19:44:37 +00:00
Mario Vavti
7d4e07df79 AccessList::is_private() does not return info about the private state (1 or 2). Use the info from the parent item until this will be sorted out 2021-05-23 19:17:09 +02:00
Mario
8211bc09d4 remove todo since the zot6 xchan should be merely imported in this case. also only return if we already have a result. 2021-05-21 06:54:37 +00:00
Mario
5705005ca3 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-05-21 06:44:21 +00:00
Mario
79b4642b32 introduce the direct flag for direct messages 2021-05-21 06:44:15 +00:00
Mario
c9981ff0e1 Merge branch 'Malend-dev-patch-02229' into 'dev'
Remove useless test

See merge request hubzilla/core!1957
2021-05-21 06:38:40 +00:00
Mario
0948b061fe Merge branch 'Malend-dev-patch-19605' into 'dev'
Fix phpDoc

See merge request hubzilla/core!1958
2021-05-21 06:37:33 +00:00
Mario
a537e78f14 Merge branch 'cherry-pick-a7a47275' into 'master'
Merge branch 'dev' into 'dev'

See merge request hubzilla/core!1960
2021-05-20 13:40:47 +00:00
Max Kostikov
25edeebf2b Merge branch 'dev' into 'dev'
Fix updated variables in member verificaton template

See merge request hubzilla/core!1959

(cherry picked from commit a7a4727591)

bc2afb21 Fix updated variables
2021-05-20 12:40:54 +00:00
Max Kostikov
a7a4727591 Merge branch 'dev' into 'dev'
Fix updated variables in member verificaton template

See merge request hubzilla/core!1959
2021-05-20 12:33:03 +00:00
Max Kostikov
bc2afb21e1 Fix updated variables 2021-05-20 12:29:37 +00:00
Mario
64fe93b9eb Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-05-20 10:15:08 +00:00
Mario
33d2a852c9 make sure to set the correct item_private state 2021-05-20 10:14:49 +00:00
Malendur
300679c053 Fix phpDoc 2021-05-20 08:23:45 +00:00
Malendur
f9c85c52f3 Remove useless test 2021-05-20 08:14:58 +00:00
Max Kostikov
98985b2761 Merge branch 'dev' into 'dev'
Fix security headers switching

See merge request hubzilla/core!1953
2021-05-19 23:30:39 +00:00
Mario
8fe00d428d bring back the channel_protocols hook 2021-05-19 17:47:26 +00:00
Max Kostikov
02229482b8 Fix security headers switching 2021-05-17 22:30:47 +02:00
Mario
9a5c1aa02f there might be errors in cli without this 2021-05-17 09:42:29 +00:00
Mario
a46e340a13 Ãmake sure we do not deal with diaspora hublocs here 2021-05-17 09:09:24 +00:00
Mario
70c3cd99ac Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-05-15 13:21:22 +00:00
Mario
e89bbde575 add zid and delegate parameters to the bdest string so that we will be authenticated when being redirected offsite 2021-05-15 13:21:07 +00:00
Mario Vavti
2ee1e2af72 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-05-15 15:16:05 +02:00
Mario Vavti
c3ad21c548 make sure we do not mess up the query string when removing single parameters 2021-05-15 15:15:48 +02:00
Mario
635a24dff4 Merge branch 'dev' into 'dev'
Random PHP 8 fixes

See merge request hubzilla/core!1951
2021-05-14 08:56:07 +00:00
Max Kostikov
a03423794a Random PHP 8 fixes 2021-05-14 08:56:06 +00:00
Mario
d4e723a8eb fix regression in regard to menu wrapping
(cherry picked from commit ded9f18b8a)
2021-05-12 08:00:59 +00:00
Mario
ded9f18b8a fix regression in regard to menu wrapping 2021-05-12 07:56:30 +00:00
nobody
a96345401f Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-04-16 04:42:45 -07:00
nobody
9359fc065c Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-04-05 23:15:01 -07:00
nobody
878be8fff0 small adjustment (effects export output but is correctly handled by import) 2021-02-24 11:48:28 -08:00
nobody
beb418b093 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-02-24 11:38:38 -08:00
nobody
0f89d2b8e0 some content fields found in the wild are actually arrays 2021-02-23 15:37:58 -08:00
nobody
fc88c306ab some minor issues uncovered during hubzilla->zap export testing 2021-02-22 17:23:08 -08:00
nobody
5664f5e0a2 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-02-18 21:42:15 -08:00
nobody
136bc13ff6 forgot these 2021-02-17 21:50:11 -08:00
nobody
62b738da95 migration testing 2021-02-17 19:42:58 -08:00
nobody
e7c7f91a3f Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-02-17 16:37:19 -08:00
nobody
8a65fc8a43 more work on hz->zap migration stuff 2021-02-17 16:36:27 -08:00
nobody
0b95e061a3 more zap export work 2021-02-17 01:15:07 -08:00
nobody
383917eb0f more zap export compatibility work 2021-02-17 01:05:30 -08:00
nobody
7e3046b85c more work on zap channel export. 2021-02-16 23:38:17 -08:00
2047 changed files with 229020 additions and 130998 deletions

7
.gitignore vendored
View File

@@ -33,8 +33,10 @@ apps/
home.html
# page header plugin
pageheader.html
# Ignore site TOS
# Ignore site TOS & gddpr
doc/SiteTOS.md
doc/*/SiteTOS.md
doc/*/gdpr.md
# themes except for redbasic
view/theme/*
!view/theme/redbasic
@@ -55,6 +57,7 @@ tests/results/
.buildpath
.externalToolBuilders
.settings/
.pydevproject
# NetBeans project folder
nbproject/
# Kdevelop project files
@@ -75,3 +78,5 @@ composer.phar
vendor/**/tests/
vendor/**/Test/
vendor/sabre/*/examples/
# /info is a directory containing site-specific HTML documents
/info/

View File

@@ -115,16 +115,16 @@ php7.3_mariadb10.3:
# PHP7.3 with PostgreSQL latest (11)
php7.3_postgres11:
<<: *job_definition_postgres
artifacts: *artifacts_template
#php7.3_postgres11:
# <<: *job_definition_postgres
# artifacts: *artifacts_template
# PHP7.3 with PostgreSQL latest (11)
php7.3_postgres11:
<<: *job_definition_postgres
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
artifacts: *artifacts_template
#php7.3_postgres11:
# <<: *job_definition_postgres
# image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
# artifacts: *artifacts_template
# Generate Doxygen API Documentation and deploy it as GitLab pages

226
CHANGELOG
View File

@@ -1,3 +1,229 @@
Hubzilla 6.4 (2021-11-09)
- Automatically connect the invitee with the inviting channel
- Use the composer version of urlify
- Implement zip file import of exported items from mod uexport
- Start sending supported protocols with the actor object
- Split up manual item export to separate sections
- Serve w3.org jsonld documents locally - issue #1637
- Support IDNA URL embedding
- Improve handling of re-installed hubs in lib HTTPSig
- BBcode support for notes widget/app
- Implement a force flag for HTTPSig::get_key()
- Update composer libs
- Use Libzot::fetch_conversation for manual content import
- Implement optional force argument in Libzot::process_delivery
- Improve german doco
- Move sync logic for apps to mod appman
- Provide sync for system apps
- Update certificates
- Return status code 410 if a channel is deleted
- Add optional argument to channelx_by_* functions to allow inclusion of removed channels
- Improve file upload performance
- Introduce progress tracking for channel cloning via network (not compatible with cloning from older versions)
- Improve channel delete performance by moving some actions to background tasks
- Introduce all in one channel cloning via network (not compatible with cloning from older versions)
- Rename zotfeed to outbox but keep an alias for compatibility
- Implement apps un-starring from the app bin via drag and drop
- Re-implement the externals daemon
- Add zot6 specific handling to onepoll
- Implement the top option in items_fetch() which will only return top level items
- Add notices tab to HQ widget
- Improve mod manage performance
- Add option to mark all notices of a thread read if a notice of the thread is clicked (default true)
- Provide a get_cached_actor_provider hook and improve the author/owner handling in Libzot::import()
Bugfixes
- Fix issue where remote channels could not create wiki pages due to wron permission check - issue #1640
- Fix dutch registration email template
- Fix selection of invite template
- Fix too restrictive email check in mod invite
- Fix photos and albums ActivityStreams 2 representation
- Fix keys always fetched from network in lib HTTPSig for some AP implementations
- Fix album display of root directory
- Fix onepoll importing to deleted channels
- Fix rendering of image tags in codeblocks
- Fix webfinger and xrd providing results for removed channels
- Fix alt_pager() providing too many arguments
- Fix drop_query_params() if no query params are provided
- Fix duplicate entries for dead hubs in delivery report
- Fix site lookup
- Fix mod locs displaying drop icons for local channels
- Fix multiple issues with propagating deletes of cloned channels
- Fix apps can be draged outsite of drop areas
- Fix removed channels counted in max id check
- Fix api_auth not fetching the id if it was not cached
- Fix public stream unseen notifications displayed allthough the app is not installed
- Fix possible storage conversion stuck on file save error
- Fix notification panel collapsed state not saved if closed manually
- Fix find_best_identity() dismissing AP hublocs
- Fix likes and commments on direct messages mixed up in notices
- Fix rewrite of links to resources in body fails if nicknames of clones differ - issue #1507
- Fix syncing outdated data due to profile sync done before the fields were updated
- Fix $desturl set to wrong value (null)
Addons
- Cart: add settings URL to the apd file
- Diaspora: remove deprecated included
- Cart: remove deprecated include
- Openid: remove library/urlify in favor of composer installed versions
- Pubcrawl: provide tags indicating the supported protocols
- Pubcrawl: if we do not get an uuid, create a v5 uuid from the mid
- Cart: fix rendering regressions from bootstrap5 upgrade
- Upgrade_info: fix dismiss button
- Pubcrawl: move fetch_provider from core to addon
- Diaspora: fix regression in fetch_provider
- Content_import: fix syntax error
- Queueworker: update priorities
- Pubcrawl: only lookup announce author if we actually deal with an announce
- Pubcrawl: make sure we have the best identity before we make the abook lookup
- Pubcrawl: outbox moved to core
- Diaspora: implement the get_cached_actor_provider hook
Hubzilla 6.2.2 (2021-10-03)
- Fix an issue which could lead to loss of photos under certain conditions
Hubzilla 6.2.1 (2021-09-16)
- Fix regression introduced in 6.2 where Diaspora comments on Hubzilla posts were not relayed
- Fix wrong variable used for refresh under certain conditions
- Fix issue where summary tag was processed in cleanup_bbcode() while it shoud not
- Fix issue where profile name change was not applied if done from non primary location
- Fix spacing issue for collapsed pinned apps with an image
- Fix language selector reloading the page if not clicking exactly the icon
- Fix regression displaying bootstrap modals introduced in 6.2
Hubzilla 6.2 (2021-09-08)
- Deprecate the custom highlight [hl] bbcode in favor of [mark] which is a html5 standard
- Check post_mail permission when receiving a direct message
- Refactor actor store and cache mechanism
- Add optional strict flag (false) to base64url_decode() which is passed on to base64_decode()
- Update russian translations
- Add optional force flag (false) to Activity::actor_store()
- Improved icon lookup for actor objects
- Improved desktop notifications
- Make Hubzilla installable as PWA in supported browsers
- Capitalized widget titles (redbasic)
- Make images loaded counter showing % loaded instead of actual image count
- Deprecate optional channel menu in favor of extended app bin
- Implement infrastructure to provide an app install widget for modules
- Implement app descriptions
- Implement app drag and drop sorting
- Implement app drag and drop pinning/starring
- Update polish translations
- Update to bootstrap 5 and adjust templates
Bugfixes
- Fix anonymous comments for cards and articles
- Resolve regex interference between contact and channel autocomplete
- Fix files stored in wrong directory when uploaded in the photo module
- Fix records with empty public key selected for OWA
- Fix import_author_zot failing if primary is both dead and unknown - issue #1599
- Fix regression with bookmarks
- Fix pubstream notifications link redirecting to mod hq when not local
- Cleanup legacy mail leftovers - issue #1595
- Fix getimagesize() called with empty path
- Fix display issue caused by redundant closing div tag
Addons
- Pubcrawl: fix post to forum - issue #159
- Diaspora: implement post_mail permissions for direct messages
- Pubcrawl: implement post_mail permissions for direct messages
- Pubcrawl: deprecate asencode_person() in favor of Activity::encode_person()
- Pubcrawl: implement Activity::get_actor_collections() to reflect core actor store changes
- Diaspora: fix use of deprecated function
- Twitter: prevent re-retweeting of a post from a clone if it has already been sent
- Totp: use platform name instead of banner text
- Pubcrawl: use force flag when updating an actor
- Sse: do not process possible empty hashes
- Implement app descriptions for addons that already support the apps infrastructure
Hubzilla 6.0.1 (2021-07-27)
- Fix regression in notification handling introduced in 6.0
- Fix regression in regard to unified session page load times introduced in 6.0
- Fix photo description textarea only available if create status post enabled
- Fix item not found by message id at clone locations
- Dismiss deleted xchans in mod chanview
Hubzilla 6.0 (2021-07-09)
- Implement swipe to right for bringing in left aside
- DB update 1247 to clean up bogus entries in updates
- DB update 1246 to mark legacy zot xchans and hublocs deleted
- Implement desktop notifications
- Emit a warning if the calendar for the created event is disabled
- Add an option to drop media for bbcode processing
- Make mod HQ the default landing page after login
- Implement direct messages view for mod HQ
- Implement public/restricted messages view for mod HQ
- Implement starred messages view for mod HQ (only available if the Star Posts feature is enabled)
- Update composer libs
- Remove deprecated mod ping
- Remove legacy zot libs and functions - major cleanup
Bugfixes
- Fix deleting and starring in unthreaded view
- Fix issue where incomplete datasets were stored into updates
- Fix photo item tags not stored and propagated
- Fix notifications not loading if a filter was applied
- Fix in browser email validation for registrations
- Fix directory sync issues
- Fix issue where the original rawmsg iconfig got overwritten
- Fix unmaintained id3 pareser for PHP8
- Fix item_private state for imported items
- Random PHP8 fixes (ongoing)
Addons
- Pubcrawl: fix ld-signature for profile updates
- Pubcrawl: deprecate as_actor_store() in favor of Activity::actor_store()
- Twitter: prevent duplicated tweets
- Remove legacy zot dpendencies and deprecated functions
- Pubcrawl: fix remote reply for peertube
- Pubcrawl: fix issue where we could end up with an xchan but without hubloc
- Diaspora: implement the direct_message_recipients hook
- Queueworker: add a simple priority mechanism to prevent not so important janitor tasks (e.g. onedirsync) stuffing up the queue and delaying delivery of items
- Pubcrawl: implement direct message recognision for activities coming from Mastodon
- Pubcrawl: always show complete threads (complete as in all the messages we have received) in public stream
- Twitter_api: remove the mail endpoint
- Mail: make interface read only with the possibility to download and delete mails (this addon will be removed in a future version)
- Pubsubhubbub: move to addons-unmaintained
- GNU-Social: move to addons-unmaintained
- Fixes to reflect core notifier changes
- Diaspora: refactor conversations a.k.a mail to implement direct messages infrastructure
- Pubcrawl: allow hublocs to be upgraded from ostatus
- Diaspora: fix issue where we could end up with an xchan but without hubloc
Hubzilla 5.6.1 (2021-06-04)
- Update spanish translations
- Fix login name label if register email verification is disabled
- Fix zotinfo issue with deleted channels
- Make pubstream ordering configurable
- Fix article summary duplicated when editing
- Update polish translations
- Fix admin setting for invitations not displayed correctly
- Fix registration in invite only mode
- Fix notifications not returning offset -1 when returning early
- Fix direct messages for items imported via sync
- Bring back the channel protocols hooks
- Fix security headers switching
- Fix magic auth for delegated channels
- Introduce drop_query_params() for secure query parameter removal
- PHP8 fixes (ongoing)
- Fix menu wrapping regression
Addons
- LDAPauth: fix regression creating an account
- Twitter: allow feeds crossposting
- Twitter: fix posting when post by default is disabled
- Pubcrawl: add litepub directMessage attribute
- Pubcrawl: allow xchan/hubloc upgrades from e.g. ostatus
- Diaspora: fix possible issue with missing hublocs
- Diaspora: refine dispatching of public of public items
Hubzilla 5.6 (2021-05-11)
- Improve postgres hubloc queries
- Implement automatic duplicate singleton hubloc removal

27
SBOM.md
View File

@@ -2,20 +2,21 @@
|Name|Version|License|Source|
|----|-------|-------|------|
|blueimp/jquery-file-upload|10.31.0.0|MIT|https://github.com/vkhramtsov/jQuery-File-Upload.git|
|brick/math|0.9.2.0|MIT|https://github.com/brick/math.git|
|blueimp/jquery-file-upload|10.32.0.0|MIT|https://github.com/vkhramtsov/jQuery-File-Upload.git|
|brick/math|0.9.3.0|MIT|https://github.com/brick/math.git|
|bshaffer/oauth2-server-php|1.11.1.0|MIT|https://github.com/bshaffer/oauth2-server-php.git|
|commerceguys/intl|1.0.7.0|MIT|https://github.com/commerceguys/intl.git|
|commerceguys/intl|1.1.0.0|MIT|https://github.com/commerceguys/intl.git|
|desandro/imagesloaded|4.1.4.0|MIT|https://github.com/desandro/imagesloaded.git|
|ezyang/htmlpurifier|4.13.0.0|LGPL-2.1-or-later|https://github.com/ezyang/htmlpurifier.git|
|league/html-to-markdown|4.10.0.0|MIT|https://github.com/thephpleague/html-to-markdown.git|
|jbroadway/urlify|1.2.2.0|BSD-3-Clause-Clear|https://github.com/jbroadway/urlify.git|
|league/html-to-markdown|5.0.1.0|MIT|https://github.com/thephpleague/html-to-markdown.git|
|lukasreschke/id3parser|0.0.3.0|GPL|https://github.com/LukasReschke/ID3Parser.git|
|michelf/php-markdown|1.9.0.0|BSD-3-Clause|https://github.com/michelf/php-markdown.git|
|pear/text_languagedetect|1.0.1.0|BSD-2-Clause|https://github.com/pear/Text_LanguageDetect.git|
|phpseclib/phpseclib|2.0.30.0|MIT|https://github.com/phpseclib/phpseclib.git|
|psr/log|1.1.3.0|MIT|https://github.com/php-fig/log.git|
|ramsey/collection|1.1.3.0|MIT|https://github.com/ramsey/collection.git|
|ramsey/uuid|4.1.1.0|MIT|https://github.com/ramsey/uuid.git|
|phpseclib/phpseclib|2.0.33.0|MIT|https://github.com/phpseclib/phpseclib.git|
|psr/log|1.1.4.0|MIT|https://github.com/php-fig/log.git|
|ramsey/collection|1.2.2.0|MIT|https://github.com/ramsey/collection.git|
|ramsey/uuid|4.2.3.0|MIT|https://github.com/ramsey/uuid.git|
|sabre/dav|4.1.5.0|BSD-3-Clause|https://github.com/sabre-io/dav.git|
|sabre/event|5.1.2.0|BSD-3-Clause|https://github.com/sabre-io/event.git|
|sabre/http|5.1.1.0|BSD-3-Clause|https://github.com/sabre-io/http.git|
@@ -23,9 +24,13 @@
|sabre/vobject|4.3.5.0|BSD-3-Clause|https://github.com/sabre-io/vobject.git|
|sabre/xml|2.2.3.0|BSD-3-Clause|https://github.com/sabre-io/xml.git|
|simplepie/simplepie|1.5.6.0|BSD-3-Clause|https://github.com/simplepie/simplepie.git|
|smarty/smarty|3.1.38.0|LGPL-3.0|https://github.com/smarty-php/smarty.git|
|symfony/polyfill-ctype|1.22.0.0|MIT|https://github.com/symfony/polyfill-ctype.git|
|twbs/bootstrap|4.6.0.0|MIT|https://github.com/twbs/bootstrap.git|
|smarty/smarty|3.1.39.0|LGPL-3.0|https://github.com/smarty-php/smarty.git|
|symfony/polyfill-ctype|1.23.0.0|MIT|https://github.com/symfony/polyfill-ctype.git|
|symfony/polyfill-php80|1.23.1.0|MIT|https://github.com/symfony/polyfill-php80.git|
|symfony/polyfill-php81|1.23.0.0|MIT|https://github.com/symfony/polyfill-php81.git|
|twbs/bootstrap|5.1.3.0|MIT|https://github.com/twbs/bootstrap.git|
|voku/portable-ascii|1.5.6.0|MIT|https://github.com/voku/portable-ascii.git|
|voku/stop-words|2.0.1.0|MIT|https://github.com/voku/stop-words.git|
|fullcalendar/fullcalendar|4.4.2.0|MIT|https://github.com/fullcalendar/fullcalendar.git|
|miromannino/Justified-Gallery|3.8.1.0|MIT|https://github.com/miromannino/Justified-Gallery.git|
|fengyuanchen/cropperjs|1.5.7.0|MIT|https://github.com/fengyuanchen/cropperjs.git|

10
ServiceWorker.js Normal file
View File

@@ -0,0 +1,10 @@
// This file should be served from the web root to avoid scope and cookie related issues with some browsers
self.addEventListener('install', function(e) {
console.log('install event');
});
self.addEventListener('fetch', function(e) {
// nothing here yet
return;
});

View File

@@ -65,9 +65,9 @@ class Permissions {
'write_wiki' => t('Can write to my wiki pages'),
'post_wall' => t('Can post on my channel (wall) page'),
'post_comments' => t('Can comment on or like my posts'),
'post_mail' => t('Can send me private mail messages'),
'post_mail' => t('Can send me direct messages'),
'post_like' => t('Can like/dislike profiles and profile things'),
'tag_deliver' => t('Can forward to all my channel connections via ! mentions in posts'),
'tag_deliver' => t('Can forward direct messages to all my channel connections (forum)'),
'chat' => t('Can chat with me'),
'republish' => t('Can source my public posts in derived channels'),
'delegate' => t('Can administer my channel')

View File

@@ -0,0 +1,34 @@
<?php
namespace Zotlabs\Daemon;
class Channel_purge {
static public function run($argc,$argv) {
cli_startup();
$channel_id = intval($argv[1]);
$channel = q("select * from channel where channel_id = %d and channel_removed = 1",
intval($channel_id)
);
if (! $channel) {
return;
}
do {
$r = q("select id from item where uid = %d and item_deleted = 0 limit 1000",
intval($channel_id)
);
if ($r) {
foreach ($r as $rv) {
drop_item($rv['id'], false);
}
}
} while ($r);
return;
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace Zotlabs\Daemon;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\PConfig;
require_once('include/cli_startup.php');
require_once('include/attach.php');
require_once('include/import.php');
class Content_importer {
static public function run($argc,$argv) {
cli_startup();
$page = $argv[1];
$since = $argv[2];
$until = $argv[3];
$channel_address = $argv[4];
$hz_server = urldecode($argv[5]);
$m = parse_url($hz_server);
$channel = channelx_by_nick($channel_address);
if(! $channel) {
logger('channel not found');
return;
}
$headers = [
'X-API-Token' => random_string(),
'X-API-Request' => $hz_server . '/api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
'Host' => $m['host'],
'(request-target)' => 'get /api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
];
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
$x = z_fetch_url($hz_server . '/api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page,false,$redirects,[ 'headers' => $headers ]);
// logger('item fetch: ' . print_r($x,true));
if(! $x['success']) {
logger('no API response',LOGGER_DEBUG);
killme();
}
$j = json_decode($x['body'],true);
if(! is_array($j['item']) || ! count($j['item'])) {
PConfig::Set($channel['channel_id'], 'import', 'content_completed', 1);
return;
}
$saved_notification_flags = notifications_off($channel['channel_id']);
import_items($channel,$j['item'],false,((array_key_exists('relocate',$j)) ? $j['relocate'] : null));
notifications_on($channel['channel_id'], $saved_notification_flags);
PConfig::Set($channel['channel_id'], 'import', 'content_progress', [
'items_total' => $j['items_total'],
'items_page' => $j['items_page'],
'items_current_page' => count($j['item']),
'last_page' => $page,
'next_cmd' => ['Content_importer', sprintf('%d',$page + 1), $since, $until, $channel['channel_address'], urlencode($hz_server)]
]);
$page++;
Master::Summon([ 'Content_importer', sprintf('%d',$page), $since, $until, $channel['channel_address'], urlencode($hz_server) ]);
return;
}
}

View File

@@ -36,7 +36,6 @@ class Cron {
// run queue delivery process in the background
Master::Summon(array('Queue'));
Master::Summon(array('Poller'));
/**
@@ -48,13 +47,7 @@ class Cron {
db_quoteinterval('3 MINUTE')
);
// expire any expired mail
q("delete from mail where expires > '%s' and expires < %s ",
dbesc(NULL_DATE),
db_utcnow()
);
require_once('include/account.php');
remove_expired_registrations();
$interval = get_config('system', 'delivery_interval', 3);
@@ -164,11 +157,6 @@ class Cron {
}
}
// check if any connections transitioned to zot6 and upgrade the connections to zot6 at this hub if so.
require_once('include/connections.php');
z6trans_connections();
require_once('include/attach.php');
attach_upgrade();
@@ -217,10 +205,9 @@ class Cron {
// pull in some public posts
/* $disable_discover_tab = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false;
$disable_discover_tab = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false;
if (!$disable_discover_tab)
Master::Summon(array('Externals'));
*/
Master::Summon(['Externals']);
$restart = false;

View File

@@ -95,8 +95,6 @@ class Cron_daily {
remove_obsolete_hublocs();
remove_duplicate_singleton_hublocs();
z6_discover();
$date = datetime_convert();
call_hooks('cron_daily', $date);

View File

@@ -2,7 +2,7 @@
namespace Zotlabs\Daemon;
require_once('include/queue_fn.php');
use Zotlabs\Lib\Queue;
class Deliver {
@@ -23,7 +23,7 @@ class Deliver {
);
if ($r) {
queue_deliver($r[0], true);
Queue::deliver($r[0], true);
}
}

View File

@@ -49,8 +49,9 @@ class Directory {
);
// Now update all the connections
if ($pushall)
if ($pushall) {
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
}
return;
}
@@ -74,7 +75,7 @@ class Directory {
* the directory packet. That means we'll try again on the next poll run.
*/
$hash = random_string();
$hash = new_uuid();
Queue::insert(array(
'hash' => $hash,
@@ -93,8 +94,8 @@ class Directory {
}
// Now update all the connections
if ($pushall)
if ($pushall) {
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
}
}
}

View File

@@ -2,6 +2,7 @@
namespace Zotlabs\Daemon;
require_once('include/items.php');
class Expire {

View File

@@ -3,6 +3,7 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\ASCollection;
@@ -31,25 +32,55 @@ class Externals {
$url = $arr['url'];
}
else {
$networks = ['zot6'];
if (plugin_is_installed('pubcrawl')) {
$networks[] = 'activitypub';
}
stringify_array_elms($networks);
$networks_str = implode(',', $networks);
$randfunc = db_getfunc('RAND');
// fixme this query does not deal with directory realms.
//$r = q("select site_url, site_pull from site where site_url != '%s'
//and site_flags != %d and site_type = %d
//and site_dead = 0 and site_project like '%s' and site_version > '5.3.1' order by $randfunc limit 1",
//dbesc(z_root()),
//intval(DIRECTORY_MODE_STANDALONE),
//intval(SITE_TYPE_ZOT),
//dbesc('hubzilla%')
//);
$r = q("select site_url, site_pull from site where site_url != '%s'
and site_flags != %d and site_type = %d
and site_dead = 0 and site_project like '%s' and site_version > '5.3.1' order by $randfunc limit 1",
$r = q("SELECT * FROM hubloc
LEFT JOIN abook ON abook_xchan = hubloc_hash
LEFT JOIN site ON site_url = hubloc_url WHERE
hubloc_network IN ( $networks_str ) AND
abook_xchan IS NULL AND
hubloc_url != '%s' AND
hubloc_updated > '%s' AND
hubloc_primary = 1 AND hubloc_deleted = 0 AND
site_dead = 0
ORDER BY $randfunc LIMIT 1",
dbesc(z_root()),
intval(DIRECTORY_MODE_STANDALONE),
intval(SITE_TYPE_ZOT),
dbesc('hubzilla%')
datetime_convert('UTC', 'UTC', 'now - 30 days')
);
if ($r)
$url = $r[0]['site_url'];
$contact = $r[0];
if ($contact) {
$url = $contact['hubloc_id_url'];
}
}
if (!$url) {
continue;
}
$blacklisted = false;
if (!check_siteallowed($url)) {
if (!check_siteallowed($contact['hubloc_url'])) {
logger('blacklisted site: ' . $url);
$blacklisted = true;
}
@@ -59,123 +90,65 @@ class Externals {
// make sure we can eventually break out if somebody blacklists all known sites
if ($blacklisted) {
if ($attempts > 20)
if ($attempts > 5)
break;
$attempts--;
continue;
}
$cl = Activity::get_actor_collections($contact['hubloc_hash']);
if(empty($cl)) {
$cl = get_xconfig($contact['hubloc_hash'], 'activitypub', 'collections');
}
if (is_array($cl) && array_key_exists('outbox', $cl)) {
$url = $cl['outbox'];
}
else {
$url = str_replace('/channel/', '/outbox/', $contact['hubloc_id_url']);
if ($url) {
$url .= '?top=1';
}
}
if ($url) {
logger('fetching outbox: ' . $url);
$max = intval(get_config('system', 'max_imported_posts', 30));
if (intval($max)) {
logger('externals: fetching outbox');
$obj = new ASCollection($url, $importer, 0, 10);
$messages = $obj->get();
$feed_url = $url . '/zotfeed';
$obj = new ASCollection($feed_url, $importer, 0, $max);
$messages = $obj->get();
if ($messages) {
foreach ($messages as $message) {
if (is_string($message)) {
$message = Activity::fetch($message, $importer);
}
if ($messages) {
foreach ($messages as $message) {
if (is_string($message)) {
$message = Activity::fetch($message, $importer);
}
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
Activity::store($importer, $importer['xchan_hash'], $AS, $item, true);
$total++;
if ($message['type'] !== 'Create') {
continue;
}
if ($contact['hubloc_network'] === 'zot6') {
// make sure we only fetch top level items
if (isset($message['object']['inReplyTo'])) {
continue;
}
Libzot::fetch_conversation($importer, $message['object']['id']);
$total++;
continue;
}
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
Activity::store($importer, $contact['abook_xchan'], $AS, $item);
$total++;
}
}
logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
}
logger('fetched messages count: ' . $total);
}
}
return;
/* $total = 0;
$attempts = 0;
logger('externals: startup', LOGGER_DEBUG);
// pull in some public posts
while ($total == 0 && $attempts < 3) {
$arr = ['url' => ''];
call_hooks('externals_url_select', $arr);
if ($arr['url']) {
$url = $arr['url'];
}
else {
$randfunc = db_getfunc('RAND');
// fixme this query does not deal with directory realms.
$r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d and site_type = %d and site_dead = 0 order by $randfunc limit 1",
dbesc(z_root()),
intval(DIRECTORY_MODE_STANDALONE),
intval(SITE_TYPE_ZOT)
);
if ($r)
$url = $r[0]['site_url'];
}
$blacklisted = false;
if (!check_siteallowed($url)) {
logger('blacklisted site: ' . $url);
$blacklisted = true;
}
$attempts++;
// make sure we can eventually break out if somebody blacklists all known sites
if ($blacklisted) {
if ($attempts > 20)
break;
$attempts--;
continue;
}
if ($url) {
if ($r[0]['site_pull'] > NULL_DATE)
$mindate = urlencode(datetime_convert('', '', $r[0]['site_pull'] . ' - 1 day'));
else {
$days = get_config('externals', 'since_days');
if ($days === false)
$days = 15;
$mindate = urlencode(datetime_convert('', '', 'now - ' . intval($days) . ' days'));
}
$feedurl = $url . '/zotfeed?f=&mindate=' . $mindate;
logger('externals: pulling public content from ' . $feedurl, LOGGER_DEBUG);
$x = z_fetch_url($feedurl);
if (($x) && ($x['success'])) {
q("update site set site_pull = '%s' where site_url = '%s'",
dbesc(datetime_convert()),
dbesc($url)
);
$j = json_decode($x['body'], true);
if ($j['success'] && $j['messages']) {
$sys = get_sys_channel();
foreach ($j['messages'] as $message) {
// on these posts, clear any route info.
$message['route'] = '';
process_delivery(['hash' => 'undefined'], get_item_elements($message),
[['hash' => $sys['xchan_hash']]], false, true);
$total++;
}
logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
}
}
}
}*/
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace Zotlabs\Daemon;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\PConfig;
require_once('include/cli_startup.php');
require_once('include/attach.php');
require_once('include/import.php');
class File_importer {
static public function run($argc,$argv) {
cli_startup();
$page = $argv[1];
$channel_address = $argv[2];
$hz_server = urldecode($argv[3]);
$m = parse_url($hz_server);
$channel = channelx_by_nick($channel_address);
if(! $channel) {
logger('channel not found');
return;
}
$headers = [
'X-API-Token' => random_string(),
'X-API-Request' => $hz_server . '/api/z/1.0/file/export_page?f=records=1&page=' . $page,
'Host' => $m['host'],
'(request-target)' => 'get /api/z/1.0/file/export_page?f=records=1&page=' . $page,
];
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),true,'sha512');
// TODO: implement total count
$x = z_fetch_url($hz_server . '/api/z/1.0/file/export_page?f=records=1&page=' . $page, false, $redirects, [ 'headers' => $headers ]);
// logger('file fetch: ' . print_r($x,true));
if(! $x['success']) {
logger('no API response',LOGGER_DEBUG);
killme();
}
$j = json_decode($x['body'],true);
if(! is_array($j['results'][0]['attach']) || ! count($j['results'][0]['attach'])) {
PConfig::Set($channel['channel_id'], 'import', 'files_completed', 1);
return;
}
$r = sync_files($channel, $j['results']);
PConfig::Set($channel['channel_id'], 'import', 'files_progress', [
'files_total' => $j['total'],
'files_page' => 1, // export page atm returns just one file
'last_page' => $page,
'next_cmd' => ['File_importer',sprintf('%d',$page + 1), $channel['channel_address'], urlencode($hz_server)]
]);
$page++;
Master::Summon([ 'File_importer',sprintf('%d',$page), $channel['channel_address'], urlencode($hz_server) ]);
return;
}
}

View File

@@ -6,23 +6,14 @@ use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Queue;
require_once('include/queue_fn.php');
require_once('include/html2plain.php');
require_once('include/conversation.php');
require_once('include/zot.php');
require_once('include/items.php');
require_once('include/bbcode.php');
/*
* This file was at one time responsible for doing all deliveries, but this caused
* big problems on shared hosting systems, where the process might get killed by the
* hosting provider and nothing would get delivered.
* It now only delivers one message under certain cases, and invokes a queued
* delivery mechanism (include/deliver.php) to deliver individual contacts at
* controlled intervals.
* This has a much better chance of surviving random processes getting killed
* by the hosting provider.
* Notifier - message dispatch and preparation for delivery
*
* The basic flow is:
* Identify the type of message
@@ -53,7 +44,6 @@ require_once('include/bbcode.php');
* event (in events.php)
* expire (in items.php)
* like (in like.php, poke.php)
* mail (in message.php)
* tag (in photos.php, poke.php, tagger.php)
* tgroup (in items.php)
* wall-new (in photos.php, item.php)
@@ -63,7 +53,6 @@ require_once('include/bbcode.php');
* ZOT
* permission_create abook_id
* permission_accept abook_id
* permission_reject abook_id
* permission_update abook_id
* refresh_all channel_id
* purge channel_id xchan_hash
@@ -71,7 +60,6 @@ require_once('include/bbcode.php');
* expire channel_id
* relay item_id (item was relayed to owner, we will deliver it as owner)
* single_activity item_id (deliver to a singleton network from the appropriate clone)
* single_mail mail_id (deliver to a singleton network from the appropriate clone)
* location channel_id
* request channel_id xchan_hash message_id
* rating xlink_id
@@ -82,10 +70,20 @@ require_once('include/bbcode.php');
class Notifier {
static public $deliveries = [];
static public $recipients = [];
static public $env_recips = [];
static public $packet_type = 'activity';
static public $encoding = 'activitystreams';
static public $encoded_item = null;
static public $channel = null;
static public $private = false;
static public function run($argc, $argv) {
if ($argc < 3)
if ($argc < 3) {
return;
}
logger('notifier: invoked: ' . print_r($argv, true), LOGGER_DEBUG);
@@ -93,153 +91,101 @@ class Notifier {
$item_id = $argv[2];
if (!$item_id)
if (!$item_id) {
return;
$sys = get_sys_channel();
$deliveries = [];
$request = false;
$mail = false;
$location = false;
$recipients = [];
$normal_mode = true;
$packet_type = 'undefined';
if ($cmd === 'mail' || $cmd === 'single_mail') {
$normal_mode = false;
$mail = true;
$private = true;
$message = q("SELECT * FROM mail WHERE id = %d LIMIT 1",
intval($item_id)
);
if (!$message) {
return;
}
xchan_mail_query($message[0]);
$uid = $message[0]['channel_id'];
$recipients[] = $message[0]['from_xchan']; // include clones
$recipients[] = $message[0]['to_xchan'];
$item = $message[0];
$encoded_item = encode_mail($item);
$s = q("select * from channel where channel_id = %d limit 1",
intval($uid)
);
if ($s)
$channel = $s[0];
}
elseif ($cmd === 'request') {
$channel_id = $item_id;
$xchan = $argv[3];
$request_message_id = $argv[4];
$s = q("select * from channel where channel_id = %d limit 1",
intval($channel_id)
);
if ($s)
$channel = $s[0];
self::$deliveries = [];
self::$recipients = [];
self::$env_recips = [];
self::$packet_type = 'activity';
self::$encoding = 'activitystreams';
self::$encoded_item = null;
self::$channel = null;
self::$private = false;
$private = true;
$recipients[] = $xchan;
$packet_type = 'request';
$normal_mode = false;
}
elseif ($cmd === 'keychange') {
$channel = channelx_by_n($item_id);
$sys = get_sys_channel();
$normal_mode = true;
$r = q("select abook_xchan from abook where abook_channel = %d",
if ($cmd === 'keychange') {
self::$channel = channelx_by_n($item_id);
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($item_id)
);
if ($r) {
foreach ($r as $rr) {
$recipients[] = $rr['abook_xchan'];
self::$recipients[] = $rr['abook_xchan'];
}
}
$private = false;
$packet_type = 'keychange';
$normal_mode = false;
self::$private = false;
self::$packet_type = 'keychange';
self::$encoded_item = get_pconfig(self::$channel['channel_id'], 'system', 'keychange');
self::$encoding = 'zot';
$normal_mode = false;
}
elseif (in_array($cmd, ['permission_update', 'permission_reject', 'permission_accept', 'permission_create'])) {
elseif (in_array($cmd, ['permission_update', 'permission_accept', 'permission_create'])) {
// Get the (single) recipient
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0",
intval($item_id)
);
if ($r) {
$uid = $r[0]['abook_channel'];
// Get the sender
$channel = channelx_by_n($uid);
if ($channel) {
$perm_update = ['sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => ''];
$recip = $r[0];
if ($cmd === 'permission_create')
call_hooks('permissions_create', $perm_update);
elseif ($cmd === 'permission_accept')
call_hooks('permissions_accept', $perm_update);
elseif ($cmd === 'permission_reject')
call_hooks('permissions_reject', $perm_update);
else
call_hooks('permissions_update', $perm_update);
// Get the sender
self::$channel = channelx_by_n($recip['abook_channel']);
if (self::$channel) {
$perm_update = ['sender' => self::$channel, 'recipient' => $recip, 'success' => false, 'deliveries' => ''];
switch ($cmd) {
case 'permission_create':
call_hooks('permissions_create', $perm_update);
break;
case 'permission_accept':
call_hooks('permissions_accept', $perm_update);
break;
case 'permission_update':
call_hooks('permissions_update', $perm_update);
break;
default:
break;
}
if ($perm_update['success']) {
if ($perm_update['deliveries']) {
$deliveries[] = $perm_update['deliveries'];
do_delivery($deliveries);
self::$deliveries[] = $perm_update['deliveries'];
do_delivery(self::$deliveries);
}
return;
}
else {
$recipients[] = $r[0]['abook_xchan'];
$private = false;
$packet_type = 'refresh';
$packet_recips = [['guid' => $r[0]['xchan_guid'], 'guid_sig' => $r[0]['xchan_guid_sig'], 'hash' => $r[0]['xchan_hash']]];
self::$recipients[] = $recip['abook_xchan'];
self::$private = false;
self::$packet_type = 'refresh';
self::$env_recips = [$recip['xchan_hash']];
}
}
}
}
elseif ($cmd === 'refresh_all') {
logger('notifier: refresh_all: ' . $item_id);
$uid = $item_id;
$channel = channelx_by_n($item_id);
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($uid)
);
if ($r) {
foreach ($r as $rr) {
$recipients[] = $rr['abook_xchan'];
}
}
$private = false;
$packet_type = 'refresh';
}
elseif ($cmd === 'location') {
logger('notifier: location: ' . $item_id);
$s = q("select * from channel where channel_id = %d limit 1",
self::$channel = channelx_by_n($item_id, true);
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($item_id)
);
if ($s)
$channel = $s[0];
$uid = $item_id;
$recipients = [];
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($uid)
);
if ($r) {
foreach ($r as $rr) {
$recipients[] = $rr['abook_xchan'];
self::$recipients[] = $rr['abook_xchan'];
}
}
$encoded_item = ['locations' => Libzot::encode_locations($channel), 'type' => 'location', 'encoding' => 'zot'];
$target_item = ['aid' => $channel['channel_account_id'], 'uid' => $channel['channel_id']];
$private = false;
$packet_type = 'location';
$location = true;
// In case we deleted the channel, our abook entry has already vanished.
// In order to be able to update our clones we need to add ourself here.
self::$recipients[] = self::$channel['channel_hash'];
self::$private = false;
self::$packet_type = 'refresh';
}
elseif ($cmd === 'purge') {
$xchan = $argv[3];
@@ -248,33 +194,27 @@ class Notifier {
return;
}
$channel = channelx_by_n($item_id);
$recipients[] = $xchan;
$private = true;
$packet_type = 'purge';
$packet_recips[] = ['hash' => $xchan];
self::$channel = channelx_by_n($item_id, true);
self::$recipients = [$xchan];
self::$private = true;
self::$packet_type = 'purge';
}
elseif ($cmd === 'purge_all') {
logger('notifier: purge_all: ' . $item_id);
$channel = channelx_by_n($item_id);
self::$channel = channelx_by_n($item_id, true);
self::$recipients = [];
self::$private = false;
self::$packet_type = 'purge';
$recipients = [];
$r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0",
$r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0",
intval($item_id)
);
if (!$r) {
return;
}
foreach ($r as $rr) {
$recipients[] = $rr['abook_xchan'];
$packet_recips[] = ['hash' => $rr['abook_xchan']];
self::$recipients[] = $rr['abook_xchan'];
}
$private = false;
$packet_type = 'purge';
}
else {
@@ -282,15 +222,14 @@ class Notifier {
// Fetch the target item
$r = q("SELECT * FROM item WHERE id = %d and parent != 0 LIMIT 1",
$r = q("SELECT * FROM item WHERE id = %d AND parent != 0",
intval($item_id)
);
if (!$r)
if (!$r) {
return;
}
xchan_query($r);
$r = fetch_post_tags($r);
$target_item = $r[0];
@@ -345,11 +284,12 @@ class Notifier {
$s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
intval($target_item['uid'])
);
if ($s)
$channel = $s[0];
if ($s) {
self::$channel = $s[0];
}
if ($channel['channel_hash'] !== $target_item['author_xchan'] && $channel['channel_hash'] !== $target_item['owner_xchan']) {
logger("notifier: Sending channel {$channel['channel_hash']} is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING);
if (self::$channel['channel_hash'] !== $target_item['author_xchan'] && self::$channel['channel_hash'] !== $target_item['owner_xchan']) {
logger("notifier: Sending channel " . self::$channel['channel_hash'] . " is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING);
return;
}
@@ -359,12 +299,13 @@ class Notifier {
}
else {
// fetch the parent item
$r = q("SELECT * from item where id = %d order by id asc",
$r = q("SELECT * FROM item WHERE id = %d",
intval($target_item['parent'])
);
if (!$r)
if (!$r) {
return;
}
if (strpos($r[0]['postopts'], 'nodeliver') !== false) {
logger('notifier: target item is undeliverable', LOGGER_DEBUG, LOG_NOTICE);
@@ -379,20 +320,17 @@ class Notifier {
}
// avoid looping of discover items 12/4/2014
if ($sys && $parent_item['uid'] == $sys['channel_id'])
if ($sys && $parent_item['uid'] == $sys['channel_id']) {
return;
}
$encoded_item = encode_item($target_item);
$m = get_iconfig($target_item, 'activitypub', 'signed_data');
// Re-use existing signature unless the activity type changed to a Tombstone, which won't verify.
$m = ((intval($target_item['item_deleted'])) ? '' : get_iconfig($target_item, 'activitypub', 'signed_data'));
if ($m) {
$activity = json_decode($m, true);
if ($m && (!intval($target_item['item_deleted']))) {
self::$encoded_item = json_decode($m, true);
}
else {
$activity = array_merge(['@context' => [
self::$encoded_item = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
@@ -401,7 +339,7 @@ class Notifier {
}
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
logger('encoded: ' . print_r($activity, true), LOGGER_DEBUG);
logger('encoded: ' . print_r(self::$encoded_item, 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.
@@ -412,9 +350,9 @@ class Notifier {
// flag on comments for an extended period. So we'll also call comment_local_origin() which looks at
// the hostname in the message_id and provides a second (fallback) opinion.
$relay_to_owner = (((!$top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item)) ? true : false);
$uplink = false;
$relay_to_owner = (!$top_level_post && intval($target_item['item_origin']) && comment_local_origin($target_item));
$uplink = false;
$upstream = false;
// $cmd === 'relay' indicates the owner is sending it to the original recipients
// don't allow the item in the relay command to relay to owner under any circumstances, it will loop
@@ -426,27 +364,34 @@ class Notifier {
if (($cmd === 'uplink') && intval($parent_item['item_uplink']) && (!$top_level_post)) {
logger('notifier: uplink');
$uplink = true;
$uplink = true;
self::$packet_type = 'response';
}
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
logger('notifier: followup relay', LOGGER_DEBUG);
$recipients = [($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']];
$private = true;
if (!$encoded_item['flags'])
$encoded_item['flags'] = [];
$encoded_item['flags'][] = 'relay';
$upstream = true;
$sendto = (($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
self::$recipients = [$sendto];
self::$private = true;
$upstream = true;
self::$packet_type = 'response';
}
else {
logger('notifier: normal distribution', LOGGER_DEBUG);
if ($cmd === 'relay')
logger('notifier: owner relay');
$upstream = false;
if ($cmd === 'relay') {
logger('owner relay (downstream delivery)');
}
else {
logger('normal (downstream) distribution', LOGGER_DEBUG);
}
if ($parent_item && $parent_item['item_private'] !== $target_item['item_private']) {
logger('conversation privacy mismatch - downstream delivery prevented');
return;
}
// if our parent is a tag_delivery recipient, uplink to the original author causing
// a delivery fork.
if (($parent_item) && intval($parent_item['item_uplink']) && (!$top_level_post) && ($cmd !== 'uplink')) {
if ($parent_item && intval($parent_item['item_uplink']) && !$top_level_post && $cmd !== 'uplink') {
// don't uplink a relayed post to the relay owner
if ($parent_item['source_xchan'] !== $parent_item['owner_xchan']) {
logger('notifier: uplinking this item');
@@ -454,98 +399,87 @@ class Notifier {
}
}
$private = false;
$recipients = collect_recipients($parent_item, $private);
if ($top_level_post) {
// remove clones who will receive the post via sync
$recipients = array_diff($recipients, [$target_item['owner_xchan']]);
}
self::$private = false;
self::$recipients = collect_recipients($parent_item, self::$private);
// FIXME add any additional recipients such as mentions, etc.
if ($top_level_post) {
// remove clones who will receive the post via sync
self::$recipients = array_values(array_diff(self::$recipients, [$target_item['owner_xchan']]));
}
// don't send deletions onward for other people's stuff
if (intval($target_item['item_deleted']) && (!intval($target_item['item_wall']))) {
logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE);
return;
}
}
}
$walltowall = (($top_level_post && $channel['xchan_hash'] === $target_item['author_xchan']) ? true : false);
// Generic delivery section, we have an encoded item and recipients
// Now start the delivery process
$x = $encoded_item;
$x['title'] = 'private';
$x['body'] = 'private';
logger('notifier: encoded item: ' . print_r($x, true), LOGGER_DATA, LOG_DEBUG);
logger('encoded item: ' . print_r(self::$encoded_item, true), LOGGER_DATA, LOG_DEBUG);
//logger('notifier: encoded activity: ' . print_r($activity,true), LOGGER_DATA, LOG_DEBUG);
stringify_array_elms($recipients);
if (!$recipients) {
stringify_array_elms(self::$recipients);
if (!self::$recipients) {
logger('no recipients');
return;
}
// logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG);
// logger('recipients: ' . print_r(self::$recipients,true), LOGGER_NORMAL, LOG_DEBUG);
$env_recips = (($private) ? [] : null);
$details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',', $recipients)) . ")");
if (!count(self::$env_recips)) {
self::$env_recips = ((self::$private) ? [] : null);
}
$recip_list = [];
$details = dbq("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',', self::$recipients)) . ")");
if ($details) {
foreach ($details as $d) {
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
if ($private) {
$env_recips[] = [
'guid' => $d['xchan_guid'],
'guid_sig' => $d['xchan_guid_sig'],
'hash' => $d['xchan_hash']
];
if (self::$private) {
self::$env_recips[] = $d['xchan_hash'];
}
}
}
$narr = [
'channel' => $channel,
'channel' => self::$channel,
'upstream' => $upstream,
'env_recips' => $env_recips,
'packet_recips' => $packet_recips,
'recipients' => $recipients,
'item' => $item,
'env_recips' => self::$env_recips,
'recipients' => self::$recipients,
'target_item' => $target_item,
'parent_item' => $parent_item,
'top_level_post' => $top_level_post,
'private' => $private,
'private' => self::$private,
'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink,
'cmd' => $cmd,
'mail' => $mail,
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
'location' => $location,
'request' => $request,
'single' => ($cmd === 'single_activity'),
'normal_mode' => $normal_mode,
'packet_type' => $packet_type,
'walltowall' => $walltowall,
'packet_type' => self::$packet_type,
'queued' => []
];
call_hooks('notifier_process', $narr);
if ($narr['queued']) {
foreach ($narr['queued'] as $pq)
$deliveries[] = $pq;
self::$deliveries[] = $pq;
}
// notifier_process can alter the recipient list
$recipients = $narr['recipients'];
$env_recips = $narr['env_recips'];
$packet_recips = $narr['packet_recips'];
self::$recipients = $narr['recipients'];
self::$env_recips = $narr['env_recips'];
if (($private) && (!$env_recips)) {
if (self::$private && !self::$env_recips) {
// shouldn't happen
logger('notifier: private message with no envelope recipients.' . print_r($argv, true), LOGGER_NORMAL, LOG_NOTICE);
return;
}
logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list, true), LOGGER_DEBUG);
@@ -554,15 +488,15 @@ class Notifier {
// Now we have collected recipients (except for external mentions, FIXME)
// Let's reduce this to a set of hubs; checking that the site is not dead.
$hubs = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc left join site on site_url = hubloc_url
where hubloc_hash in (" . protect_sprintf(implode(',', $recipients)) . ")
$hubs = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_dead from hubloc left join site on site_url = hubloc_url
where hubloc_hash in (" . protect_sprintf(implode(',', self::$recipients)) . ")
and hubloc_error = 0 and hubloc_deleted = 0"
);
// public posts won't make it to the local public stream unless there's a recipient on this site.
// This code block sees if it's a public post and localhost is missing, and if so adds an entry for the local sys channel to the $hubs list
if (!$private) {
if (!self::$private) {
$found_localhost = false;
if ($hubs) {
foreach ($hubs as $h) {
@@ -573,12 +507,12 @@ class Notifier {
}
}
if (!$found_localhost) {
$localhub = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc
left join site on site_url = hubloc_url where hubloc_id_url = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
$localhub = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_dead from hubloc left join site on site_url = hubloc_url
where hubloc_id_url = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
dbesc(z_root() . '/channel/sys')
);
if ($localhub) {
$hubs = array_merge($hubs, $localhub);
$hubs = array_merge($localhub, $hubs);
}
}
}
@@ -595,41 +529,34 @@ class Notifier {
*/
$hublist = []; // this provides an easily printable list for the logs
$dhubs = []; // delivery hubs where we store our resulting unique array
$keys = []; // array of keys to check uniquness for zot hubs
$urls = []; // array of urls to check uniqueness of hubs from other networks
$hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
$dead = []; // known dead hubs - report them as undeliverable
$hublist = []; // this provides an easily printable list for the logs
$dhubs = []; // delivery hubs where we store our resulting unique array
$keys = []; // array of keys to check uniquness for zot hubs
$urls = []; // array of urls to check uniqueness of hubs from other networks
$hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
$dead_hosts = []; // known dead hubs - report them as undeliverable
foreach ($hubs as $hub) {
if (intval($hub['site_dead'])) {
$dead[] = $hub;
if (isset($hub['site_dead']) && intval($hub['site_dead'])) {
if(!in_array($hub['hubloc_host'], $dead_hosts)) {
$dead_hosts[] = $hub['hubloc_host'];
}
continue;
}
if ($env_recips) {
foreach ($env_recips as $er) {
if ($hub['hubloc_hash'] === $er['hash']) {
if (!array_key_exists($hub['hubloc_host'] . $hub['hubloc_sitekey'], $hub_env)) {
$hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] = [];
if (self::$env_recips) {
foreach (self::$env_recips as $er) {
if ($hub['hubloc_hash'] === $er) {
if (!array_key_exists($hub['hubloc_site_id'], $hub_env)) {
$hub_env[$hub['hubloc_site_id']] = [];
}
$hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']][] = $er;
$hub_env[$hub['hubloc_site_id']][] = $er;
}
}
}
if ($hub['hubloc_network'] == 'zot') {
if ($hub['hubloc_network'] === 'zot6') {
if (!in_array($hub['hubloc_sitekey'], $keys)) {
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
$dhubs[] = $hub;
$keys[] = $hub['hubloc_sitekey'];
}
}
else {
if (!in_array($hub['hubloc_url'], $urls)) {
if ($hub['hubloc_url'] === z_root()) {
//deliver to local hub first
array_unshift($hublist, $hub['hubloc_host'] . ' ' . $hub['hubloc_network']);
@@ -639,7 +566,14 @@ class Notifier {
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
$dhubs[] = $hub;
}
$urls[] = $hub['hubloc_url'];
$keys[] = $hub['hubloc_sitekey'];
}
}
else {
if (!in_array($hub['hubloc_url'], $urls)) {
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
$dhubs[] = $hub;
$urls[] = $hub['hubloc_url'];
}
}
}
@@ -650,37 +584,30 @@ class Notifier {
logger('notifier_hub: ' . $hub['hubloc_url'], LOGGER_DEBUG);
if (!in_array($hub['hubloc_network'], ['zot', 'zot6'])) {
if ($hub['hubloc_network'] !== 'zot6') {
$narr = [
'channel' => $channel,
'channel' => self::$channel,
'upstream' => $upstream,
'env_recips' => $env_recips,
'packet_recips' => $packet_recips,
'recipients' => $recipients,
'item' => $item,
'env_recips' => self::$env_recips,
'recipients' => self::$recipients,
'target_item' => $target_item,
'parent_item' => $parent_item,
'hub' => $hub,
'top_level_post' => $top_level_post,
'private' => $private,
'private' => self::$private,
'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink,
'cmd' => $cmd,
'mail' => $mail,
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
'location' => $location,
'request' => $request,
'single' => $cmd === 'single_activity',
'normal_mode' => $normal_mode,
'packet_type' => $packet_type,
'walltowall' => $walltowall,
'packet_type' => self::$packet_type,
'queued' => []
];
call_hooks('notifier_hub', $narr);
if ($narr['queued']) {
foreach ($narr['queued'] as $pq)
$deliveries[] = $pq;
self::$deliveries[] = $pq;
}
continue;
@@ -695,175 +622,83 @@ class Notifier {
// will invoke a delivery to those connections which are connected to just that
// hub instance.
if ($cmd === 'single_mail' || $cmd === 'single_activity') {
if ($cmd === 'single_activity') {
continue;
}
if (!in_array($hub['hubloc_network'], ['zot', 'zot6'])) {
// default: zot protocol
$hash = new_uuid();
$env = (($hub_env && $hub_env[$hub['hubloc_site_id']]) ? $hub_env[$hub['hubloc_site_id']] : '');
if ((self::$private) && (!$env)) {
continue;
}
// Do not change this to a uuid as long as we have traditional zot servers
// in the loop. The signature verification step can't handle dashes in the
// hashes.
$packet = Libzot::build_packet(self::$channel, self::$packet_type, $env, self::$encoded_item, self::$encoding, ((self::$private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto']);
$hash = random_string(48);
Queue::insert(
[
'hash' => $hash,
'account_id' => self::$channel['channel_account_id'],
'channel_id' => self::$channel['channel_id'],
'posturl' => $hub['hubloc_callback'],
'notify' => $packet,
'msg' => EMPTY_STR
]
);
$packet = null;
$pmsg = '';
if ($packet_type === 'refresh' || $packet_type === 'purge') {
if ($hub['hubloc_network'] === 'zot6') {
$packet = Libzot::build_packet($channel, $packet_type, ids_to_array($packet_recips, 'hash'));
}
else {
$packet = zot_build_packet($channel, $packet_type, (($packet_recips) ? $packet_recips : null));
}
}
if ($packet_type === 'keychange' && $hub['hubloc_network'] === 'zot') {
$pmsg = get_pconfig($channel['channel_id'], 'system', 'keychange');
$packet = zot_build_packet($channel, $packet_type, (($packet_recips) ? $packet_recips : null));
}
elseif ($packet_type === 'request' && $hub['hubloc_network'] === 'zot') {
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
$packet = zot_build_packet($channel, $packet_type, $env, $hub['hubloc_sitekey'], $hub['site_crypto'],
$hash, ['message_id' => $request_message_id]
// only create delivery reports for normal undeleted items
if (is_array($target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
dbesc($target_item['mid']),
dbesc($hub['hubloc_host']),
dbesc($hub['hubloc_host']),
dbesc($hub['hubloc_host']),
dbesc('queued'),
dbesc(datetime_convert()),
dbesc(self::$channel['channel_hash']),
dbesc($hash)
);
}
if ($packet) {
Queue::insert(
[
'hash' => $hash,
'account_id' => $channel['channel_account_id'],
'channel_id' => $channel['channel_id'],
'posturl' => $hub['hubloc_callback'],
'driver' => $hub['hubloc_network'],
'notify' => $packet,
'msg' => (($pmsg) ? json_encode($pmsg) : '')
]
);
}
else {
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
self::$deliveries[] = $hash;
if ($hub['hubloc_network'] === 'zot6') {
$zenv = [];
if ($env) {
foreach ($env as $e) {
$zenv[] = $e['hash'];
}
}
$packet_type = (($upstream || $uplink) ? 'response' : 'activity');
// block zot private reshares from zot6, as this could cause a number of privacy issues
// due to parenting differences between the reshare implementations. In zot a reshare is
// a standalone parent activity and in zot6 it is a followup/child of the original activity.
// For public reshares, some comments to the reshare on the zot fork will not make it to zot6
// due to these different message models. This cannot be prevented at this time.
if ($packet_type === 'activity' && $activity['type'] === 'Announce' && intval($target_item['item_private'])) {
continue;
}
$packet = Libzot::build_packet($channel, $packet_type, $zenv, $activity, 'activitystreams', (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto']);
}
else {
// currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
// with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
// to trigger dequeue'ing
$z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (!array_key_exists('allow_cid', $encoded_item))) ? true : false);
if ($z6) {
$packet = zot6_build_packet($channel, 'notify', $env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'], $hash);
}
else {
$packet = zot_build_packet($channel, 'notify', $env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'], $hash);
}
}
// remove this after most hubs have updated to version 5.0
if (stripos($hub['site_project'], 'hubzilla') !== false && version_compare($hub['site_version'], '4.7.3', '<=')) {
if ($encoded_item['type'] === 'mail') {
$encoded_item['from']['network'] = 'zot';
$encoded_item['from']['guid_sig'] = str_replace('sha256.', '', $encoded_item['from']['guid_sig']);
}
else {
$encoded_item['owner']['network'] = 'zot';
$encoded_item['owner']['guid_sig'] = str_replace('sha256.', '', $encoded_item['owner']['guid_sig']);
if (strpos($encoded_item['author']['url'], z_root()) === 0) {
$encoded_item['author']['network'] = 'zot';
$encoded_item['author']['guid_sig'] = str_replace('sha256.', '', $encoded_item['author']['guid_sig']);
}
}
}
Queue::insert(
[
'hash' => $hash,
'account_id' => $target_item['aid'],
'channel_id' => $target_item['uid'],
'posturl' => $hub['hubloc_callback'],
'driver' => $hub['hubloc_network'],
'notify' => $packet,
'msg' => json_encode($encoded_item)
]
);
// only create delivery reports for normal undeleted items
if (is_array($target_item) && array_key_exists('postopts', $target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ",
dbesc($target_item['mid']),
dbesc($hub['hubloc_host']),
dbesc($hub['hubloc_host']),
dbesc('queued'),
dbesc(datetime_convert()),
dbesc($channel['channel_hash']),
dbesc($hash)
);
}
}
$deliveries[] = $hash;
}
if ($normal_mode) {
// This wastes a process if there are no delivery hooks configured, so check this before launching the new process
$x = q("select * from hook where hook = 'notifier_normal'");
if ($x) {
Master::Summon(['Deliver_hooks', $target_item['id']]);
}
}
if ($deliveries)
do_delivery($deliveries);
if (self::$deliveries) {
do_delivery(self::$deliveries);
}
logger('notifier: basic loop complete.', LOGGER_DEBUG);
if ($dead) {
foreach ($dead as $deceased) {
if (is_array($target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
dbesc($target_item['mid']),
dbesc($deceased['hubloc_host']),
dbesc($deceased['hubloc_host']),
dbesc($deceased['hubloc_host']),
dbesc('undeliverable/unresponsive site'),
dbesc(datetime_convert()),
dbesc($channel['channel_hash']),
dbesc(random_string(48))
);
}
if ($dead_hosts && is_array($target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
foreach ($dead_hosts as $deceased_host) {
$r = q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
dbesc($target_item['mid']),
dbesc($deceased_host),
dbesc($deceased_host),
dbesc($deceased_host),
dbesc('undeliverable/unresponsive site'),
dbesc(datetime_convert()),
dbesc(self::$channel['channel_hash']),
dbesc(new_uuid())
);
}
}
call_hooks('notifier_end', $target_item);
logger('notifer: complete.');
return;
}

View File

@@ -5,10 +5,6 @@ namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Libzotdir;
require_once('include/zot.php');
require_once('include/dir_fns.php');
class Onedirsync {
static public function run($argc, $argv) {
@@ -29,6 +25,7 @@ class Onedirsync {
if (!$r)
return;
if (($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (!$r[0]['ud_addr']))
return;
@@ -54,25 +51,24 @@ class Onedirsync {
// ignore doing an update if this ud_addr refers to a known dead hubloc
$h = q("select * from hubloc where hubloc_addr = '%s'",
dbesc($r[0]['ud_addr'])
dbesc($r[0]['ud_addr']),
);
$h = Libzot::zot_record_preferred($h);
if (($h) && ($h['hubloc_status'] & HUBLOC_OFFLINE)) {
if (($h) && (($h['hubloc_status'] & HUBLOC_OFFLINE) || $h['hubloc_deleted'] || $h['hubloc_error'])) {
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
intval(UPDATE_FLAGS_UPDATED),
intval(UPDATE_FLAGS_DELETED),
dbesc($r[0]['ud_addr']),
intval(UPDATE_FLAGS_UPDATED)
);
return;
}
// we might have to pull this out some day, but for now update_directory_entry()
// runs zot_finger() and is kind of zot specific
if ($h && !in_array($h['hubloc_network'], ['zot6', 'zot']))
if ($h && $h['hubloc_network'] !== 'zot6')
return;
Libzotdir::update_directory_entry($r[0]);

View File

@@ -8,6 +8,7 @@ use Zotlabs\Lib\ASCollection;
use Zotlabs\Lib\Libzot;
require_once('include/socgraph.php');
require_once('include/feedutils.php');
class Onepoll {
@@ -44,18 +45,14 @@ class Onepoll {
return;
}
$contact = array_shift($contacts);
$contact = $contacts[0];
$importer_uid = $contact['abook_channel'];
$r = q("SELECT * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
intval($importer_uid)
);
$importer = channelx_by_n($importer_uid);
if (!$r)
if (!$importer)
return;
$importer = $r[0];
logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= NULL_DATE))
@@ -75,16 +72,12 @@ class Onepoll {
return;
}
if (!in_array($contact['xchan_network'], ['zot', 'zot6']))
if ($contact['xchan_network'] !== 'zot6')
return;
// update permissions
if ($contact['xchan_network'] === 'zot6')
$x = Libzot::refresh($contact, $importer);
if ($contact['xchan_network'] === 'zot')
$x = zot_refresh($contact, $importer);
$x = Libzot::refresh($contact, $importer);
$responded = false;
$updated = datetime_convert();
@@ -109,46 +102,63 @@ class Onepoll {
return;
$fetch_feed = true;
$x = null;
// They haven't given us permission to see their stream
$can_view_stream = intval(get_abconfig($importer_uid, $contact['abook_xchan'], 'their_perms', 'view_stream'));
if (!$can_view_stream)
if (!$can_view_stream) {
$fetch_feed = false;
}
// we haven't given them permission to send us their stream
$can_send_stream = intval(get_abconfig($importer_uid, $contact['abook_xchan'], 'my_perms', 'send_stream'));
if (!$can_send_stream)
if (!$can_send_stream) {
$fetch_feed = false;
}
if ($fetch_feed && $contact['xchan_network'] !== 'zot') {
if ($fetch_feed) {
$max = intval(get_config('system', 'max_imported_posts', 30));
if (intval($max)) {
$cl = get_xconfig($contact['abook_xchan'], 'activitypub', 'collections');
$cl = Activity::get_actor_collections($contact['abook_xchan']);
if(empty($cl)) {
$cl = get_xconfig($contact['abook_xchan'], 'activitypub', 'collections');
}
if (is_array($cl) && $cl) {
$url = ((array_key_exists('outbox', $cl)) ? $cl['outbox'] : '');
if (is_array($cl) && array_key_exists('outbox', $cl)) {
$url = $cl['outbox'];
}
else {
$url = str_replace('/poco/', '/zotfeed/', $contact['xchan_connurl']);
$url = str_replace('/poco/', '/outbox/', $contact['xchan_connurl']);
}
if ($url) {
logger('fetching outbox');
$url = $url . '?date_begin=' . urlencode($last_update);
$url = $url . '?date_begin=' . urlencode($last_update);
if($contact['xchan_network'] === 'zot6') {
$url = $url . '&top=1';
}
$obj = new ASCollection($url, $importer, 0, $max);
$messages = $obj->get();
if ($messages) {
foreach ($messages as $message) {
if (is_string($message)) {
$message = Activity::fetch($message, $importer);
}
if ($contact['xchan_network'] === 'zot6') {
// make sure we only fetch top level items
if ($message['type'] === 'Create' && !isset($message['object']['inReplyTo'])) {
Libzot::fetch_conversation($importer, $message['object']['id']);
}
continue;
}
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
@@ -163,8 +173,10 @@ class Onepoll {
// update the poco details for this connection
$r = q("SELECT xlink_id from xlink where xlink_xchan = '%s' and xlink_updated > %s - INTERVAL %s and xlink_static = 0 limit 1",
intval($contact['xchan_hash']),
db_utcnow(), db_quoteinterval('1 DAY')
db_utcnow(),
db_quoteinterval('1 DAY')
);
if (!$r) {
poco_load($contact['xchan_hash'], $contact['xchan_connurl']);
}

View File

@@ -69,11 +69,11 @@ class Poller {
abook.abook_channel, abook.abook_id, abook.abook_archived, abook.abook_pending,
abook.abook_ignored, abook.abook_blocked,
xchan.xchan_network,
account.account_lastlog, account.account_flags
FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
account.account_lastlog, account.account_flags
FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
LEFT JOIN account on abook_account = account_id
where abook_self = 0
$sql_extra
$sql_extra
AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
intval(ACCOUNT_OK),
intval(ACCOUNT_UNVERIFIED) // FIXME
@@ -102,8 +102,7 @@ class Poller {
continue;
}
if (!in_array($contact['xchan_network'], ['zot', 'zot6']))
if ($contact['xchan_network'] !== 'zot6')
continue;
if ($c == $t) {
@@ -191,7 +190,7 @@ class Poller {
set_config('system', 'lastpoll', datetime_convert());
//All done - clear the lockfile
//All done - clear the lockfile
@unlink($lockfile);

View File

@@ -2,8 +2,7 @@
namespace Zotlabs\Daemon;
require_once('include/queue_fn.php');
require_once('include/zot.php');
use Zotlabs\Lib\Queue as LibQueue;
class Queue {
@@ -48,17 +47,17 @@ class Queue {
else {
// For the first 12 hours we'll try to deliver every 15 minutes
// After that, we'll only attempt delivery once per hour.
// This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
// After that, we'll only attempt delivery once per hour.
// This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
// so that we don't start off a thousand deliveries for a couple of dead hubs.
// The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
// Other drivers will have to do something different here and may need their own query.
// Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
// Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
// "every 15 minutes" category. We probably need to prioritise them when inserted into the queue
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
// or twice a day.
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
// or twice a day.
$sqlrandfunc = db_getfunc('rand');
@@ -67,7 +66,7 @@ class Queue {
);
while ($r) {
foreach ($r as $rv) {
queue_deliver($rv);
LibQueue::deliver($rv);
}
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
db_utcnow()
@@ -78,7 +77,7 @@ class Queue {
return;
foreach ($r as $rv) {
queue_deliver($rv);
LibQueue::deliver($rv);
}
}
}

View File

@@ -1,126 +0,0 @@
<?php
namespace Zotlabs\Daemon;
require_once('include/zot.php');
require_once('include/queue_fn.php');
class Ratenotif {
static public function run($argc,$argv) {
// Deprecated
return;
require_once("datetime.php");
require_once('include/items.php');
if($argc < 3)
return;
logger('ratenotif: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
$cmd = $argv[1];
$item_id = $argv[2];
if($cmd === 'rating') {
$r = q("select * from xlink where xlink_id = %d and xlink_static = 1 limit 1",
intval($item_id)
);
if(! $r) {
logger('rating not found');
return;
}
$encoded_item = array(
'type' => 'rating',
'encoding' => 'zot',
'target' => $r[0]['xlink_link'],
'rating' => intval($r[0]['xlink_rating']),
'rating_text' => $r[0]['xlink_rating_text'],
'signature' => $r[0]['xlink_sig'],
'edited' => $r[0]['xlink_updated']
);
}
$channel = channelx_by_hash($r[0]['xlink_xchan']);
if(! $channel) {
logger('no channel');
return;
}
$primary = get_directory_primary();
if(! $primary)
return;
$interval = ((get_config('system','delivery_interval') !== false)
? intval(get_config('system','delivery_interval')) : 2 );
$deliveries_per_process = intval(get_config('system','delivery_batch_count'));
if($deliveries_per_process <= 0)
$deliveries_per_process = 1;
$deliver = array();
$x = z_fetch_url($primary . '/regdir');
if($x['success']) {
$j = json_decode($x['body'],true);
if($j && $j['success'] && is_array($j['directories'])) {
foreach($j['directories'] as $h) {
if($h == z_root())
continue;
$hash = random_string();
$n = zot_build_packet($channel,'notify',null,null,'',$hash);
queue_insert(array(
'hash' => $hash,
'account_id' => $channel['channel_account_id'],
'channel_id' => $channel['channel_id'],
'posturl' => $h . '/post',
'notify' => $n,
'msg' => json_encode($encoded_item)
));
$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) {
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
update_queue_item($hash);
continue;
}
$deliver[] = $hash;
if(count($deliver) >= $deliveries_per_process) {
Master::Summon(array('Deliver',$deliver));
$deliver = array();
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
}
// catch any stragglers
if(count($deliver)) {
Master::Summon(array('Deliver',$deliver));
}
}
}
logger('ratenotif: complete.');
return;
}
}

View File

@@ -45,7 +45,6 @@ class Thumbnail {
return;
}
$default_controller = null;
$files = glob('Zotlabs/Thumbs/*.php');

View File

@@ -11,6 +11,7 @@ use Zotlabs\Web\HTTPSig;
require_once('include/event.php');
require_once('include/html2plain.php');
require_once('include/items.php');
class Activity {
@@ -41,9 +42,6 @@ class Activity {
if ($x['type'] === ACTIVITY_OBJ_EVENT) {
return self::fetch_event($x);
}
if ($x['type'] === ACTIVITY_OBJ_PHOTO) {
return self::fetch_image($x);
}
call_hooks('encode_object', $x);
}
@@ -104,7 +102,7 @@ class Activity {
if ($x['success']) {
$m = parse_url($url);
if ($m) {
$y = [ 'scheme' => $m['scheme'], 'host' => $m['host'] ];
$y = ['scheme' => $m['scheme'], 'host' => $m['host']];
if (array_key_exists('port', $m))
$y['port'] = $m['port'];
$site_url = unparse_url($y);
@@ -193,6 +191,7 @@ class Activity {
}
static function fetch_image($x) {
$ret = [
'type' => 'Image',
'id' => $x['id'],
@@ -287,21 +286,21 @@ class Activity {
'type' => $type . 'Page',
];
$numpages = $total / App::$pager['itemspage'];
$lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
$numpages = $total / App::$pager['itemspage'];
$lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
$url_parts = parse_url($id);
$ret['partOf'] = z_root() . '/' . $url_parts['path'];
$extra_query_args = '';
$query_args = null;
if(isset($url_parts['query'])) {
$query_args = null;
if (isset($url_parts['query'])) {
parse_str($url_parts['query'], $query_args);
}
if(is_array($query_args)) {
if (is_array($query_args)) {
unset($query_args['page']);
foreach($query_args as $k => $v)
foreach ($query_args as $k => $v)
$extra_query_args .= '&' . urlencode($k) . '=' . urlencode($v);
}
@@ -375,12 +374,34 @@ class Activity {
return $ret;
}
static function encode_simple_collection($items, $id, $type, $total = 0, $extra = null) {
$ret = [
'id' => z_root() . '/' . $id,
'type' => $type,
'totalItems' => $total,
];
if ($extra) {
$ret = array_merge($ret, $extra);
}
if ($items) {
if ($type === 'OrderedCollection') {
$ret['orderedItems'] = $items;
}
else {
$ret['items'] = $items;
}
}
return $ret;
}
static function encode_item($i) {
$ret = [];
if ($i['verb'] === ACTIVITY_FRIEND) {
// Hubzilla 'make-friend' activity, no direct mapping from AS1 to AS2 - make it a note
$objtype = 'Note';
@@ -591,13 +612,11 @@ class Activity {
break;
case 'Mention':
$mention_type = substr($t['name'], 0, 1);
if ($mention_type === '!') {
$ret[] = ['ttype' => TERM_FORUM, 'url' => $t['href'], 'term' => escape_tags(substr($t['name'], 1))];
}
else {
$ret[] = ['ttype' => TERM_MENTION, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '@') ? substr($t['name'], 1) : $t['name'])];
}
$ret[] = ['ttype' => TERM_MENTION, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '@') ? substr($t['name'], 1) : $t['name'])];
break;
case 'Bookmark':
$ret[] = ['ttype' => TERM_BOOKMARK, 'url' => $t['href'], 'term' => escape_tags($t['name'])];
break;
default:
@@ -624,14 +643,14 @@ class Activity {
}
break;
case TERM_FORUM:
$ret[] = ['type' => 'Mention', 'href' => $t['url'], 'name' => '!' . $t['term']];
break;
case TERM_MENTION:
$ret[] = ['type' => 'Mention', 'href' => $t['url'], 'name' => '@' . $t['term']];
break;
case TERM_BOOKMARK:
$ret[] = ['type' => 'Bookmark', 'href' => $t['url'], 'name' => $t['term']];
break;
default:
break;
}
@@ -649,7 +668,7 @@ class Activity {
$atts = ((is_array($item['attach'])) ? $item['attach'] : json_decode($item['attach'], true));
if ($atts) {
foreach ($atts as $att) {
if (strpos($att['type'], 'image')) {
if (isset($att['type']) && strpos($att['type'], 'image')) {
$ret[] = ['type' => 'Image', 'url' => $att['href']];
}
else {
@@ -758,7 +777,9 @@ class Activity {
if (array_path_exists('object/id', $obj)) {
$obj['object'] = $obj['object']['id'];
}
unset($obj['cc']);
if (isset($obj['cc'])) {
unset($obj['cc']);
}
$obj['to'] = [ACTIVITY_PUBLIC_INBOX];
$ret['object'] = $obj;
}
@@ -1094,7 +1115,33 @@ class Activity {
'height' => 300,
'width' => 300,
];
$ret['url'] = $p['xchan_url'];
/* This could be used to distinguish actors by protocol instead of tags,
* array urls are not supported by some AP projects (pixelfed) though.
*
$ret['url'] = [
[
'type' => 'Link',
'rel' => 'alternate',
'mediaType' => 'application/x-zot+json',
'href' => $p['xchan_url']
],
[
'type' => 'Link',
'rel' => 'alternate',
'mediaType' => 'application/activity+json',
'href' => $p['xchan_url']
],
[
'type' => 'Link',
'rel' => 'alternate', // 'me'?
'mediaType' => 'text/html',
'href' => $p['xchan_url']
]
];
*/
$ret['url'] = $p['xchan_url'];
$ret['publicKey'] = [
'id' => $p['xchan_url'],
@@ -1102,8 +1149,18 @@ class Activity {
'publicKeyPem' => $p['xchan_pubkey']
];
if ($c) {
$ret['tag'][] = [
'type' => 'PropertyValue',
'name' => 'Protocol',
'value' => 'zot6'
];
$ret['outbox'] = z_root() . '/outbox/' . $c['channel_address'];
}
$arr = [
'xchan' => $p,
'xchan' => $p,
'encoded' => $ret
];
@@ -1117,8 +1174,8 @@ class Activity {
$ret = [];
if ($item[$elm]) {
if (! is_array($item[$elm])) {
$item[$elm] = json_decode($item[$elm],true);
if (!is_array($item[$elm])) {
$item[$elm] = json_decode($item[$elm], true);
}
if ($item[$elm]['type'] === ACTIVITY_OBJ_PHOTO) {
$item[$elm]['id'] = $item['mid'];
@@ -1148,22 +1205,22 @@ class Activity {
}
$acts = [
'http://activitystrea.ms/schema/1.0/post' => 'Create',
'http://activitystrea.ms/schema/1.0/share' => 'Announce',
'http://activitystrea.ms/schema/1.0/update' => 'Update',
'http://activitystrea.ms/schema/1.0/like' => 'Like',
'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
'http://purl.org/zot/activity/dislike' => 'Dislike',
'http://activitystrea.ms/schema/1.0/tag' => 'Add',
'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
'http://activitystrea.ms/schema/1.0/post' => 'Create',
'http://activitystrea.ms/schema/1.0/share' => 'Announce',
'http://activitystrea.ms/schema/1.0/update' => 'Update',
'http://activitystrea.ms/schema/1.0/like' => 'Like',
'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
'http://purl.org/zot/activity/dislike' => 'Dislike',
'http://activitystrea.ms/schema/1.0/tag' => 'Add',
'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
'http://activitystrea.ms/schema/1.0/stop-following' => 'Unfollow',
'http://purl.org/zot/activity/attendyes' => 'Accept',
'http://purl.org/zot/activity/attendno' => 'Reject',
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
'Invite' => 'Invite',
'Delete' => 'Delete',
'Undo' => 'Undo'
'http://purl.org/zot/activity/attendyes' => 'Accept',
'http://purl.org/zot/activity/attendno' => 'Reject',
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
'Invite' => 'Invite',
'Delete' => 'Delete',
'Undo' => 'Undo'
];
call_hooks('activity_mapper', $acts);
@@ -1196,22 +1253,22 @@ class Activity {
static function activity_decode_mapper($verb) {
$acts = [
'http://activitystrea.ms/schema/1.0/post' => 'Create',
'http://activitystrea.ms/schema/1.0/share' => 'Announce',
'http://activitystrea.ms/schema/1.0/update' => 'Update',
'http://activitystrea.ms/schema/1.0/like' => 'Like',
'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
'http://purl.org/zot/activity/dislike' => 'Dislike',
'http://activitystrea.ms/schema/1.0/tag' => 'Add',
'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
'http://activitystrea.ms/schema/1.0/post' => 'Create',
'http://activitystrea.ms/schema/1.0/share' => 'Announce',
'http://activitystrea.ms/schema/1.0/update' => 'Update',
'http://activitystrea.ms/schema/1.0/like' => 'Like',
'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
'http://purl.org/zot/activity/dislike' => 'Dislike',
'http://activitystrea.ms/schema/1.0/tag' => 'Add',
'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
'http://activitystrea.ms/schema/1.0/stop-following' => 'Unfollow',
'http://purl.org/zot/activity/attendyes' => 'Accept',
'http://purl.org/zot/activity/attendno' => 'Reject',
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
'Invite' => 'Invite',
'Delete' => 'Delete',
'Undo' => 'Undo'
'http://purl.org/zot/activity/attendyes' => 'Accept',
'http://purl.org/zot/activity/attendno' => 'Reject',
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
'Invite' => 'Invite',
'Delete' => 'Delete',
'Undo' => 'Undo'
];
call_hooks('activity_decode_mapper', $acts);
@@ -1323,7 +1380,7 @@ class Activity {
*
*/
if (in_array($act->type, [ 'Follow', 'Invite', 'Join'])) {
if (in_array($act->type, ['Follow', 'Invite', 'Join'])) {
$their_follow_id = $act->id;
}
@@ -1346,8 +1403,8 @@ class Activity {
}
}
$x = \Zotlabs\Access\PermissionRoles::role_perms('social');
$their_perms = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']);
$x = PermissionRoles::role_perms('social');
$their_perms = Permissions::FilledPerms($x['perms_connect']);
if ($contact && $contact['abook_id']) {
@@ -1421,7 +1478,7 @@ class Activity {
}
$ret = $r[0];
$p = \Zotlabs\Access\Permissions::connect_perms($channel['channel_id']);
$p = Permissions::connect_perms($channel['channel_id']);
$my_perms = $p['perms'];
$automatic = $p['automatic'];
@@ -1442,13 +1499,13 @@ class Activity {
]
);
if($my_perms)
foreach($my_perms as $k => $v)
set_abconfig($channel['channel_id'],$ret['xchan_hash'],'my_perms',$k,$v);
if ($my_perms)
foreach ($my_perms as $k => $v)
set_abconfig($channel['channel_id'], $ret['xchan_hash'], 'my_perms', $k, $v);
if($their_perms)
foreach($their_perms as $k => $v)
set_abconfig($channel['channel_id'],$ret['xchan_hash'],'their_perms',$k,$v);
if ($their_perms)
foreach ($their_perms as $k => $v)
set_abconfig($channel['channel_id'], $ret['xchan_hash'], 'their_perms', $k, $v);
if ($r) {
logger("New ActivityPub follower for {$channel['channel_name']}");
@@ -1532,10 +1589,54 @@ class Activity {
return;
}
static function actor_store($url, $person_obj) {
static function actor_store($url, $person_obj, $force = false) {
if (!is_array($person_obj))
if (!is_array($person_obj)) {
return;
}
/* not implemented
if (array_key_exists('movedTo',$person_obj) && $person_obj['movedTo'] && ! is_array($person_obj['movedTo'])) {
$tgt = self::fetch($person_obj['movedTo']);
if (is_array($tgt)) {
self::actor_store($person_obj['movedTo'],$tgt);
ActivityPub::move($person_obj['id'],$tgt);
}
return;
}
*/
$ap_hubloc = null;
$hublocs = self::get_actor_hublocs($url);
if ($hublocs) {
foreach ($hublocs as $hub) {
if ($hub['hubloc_network'] === 'activitypub') {
$ap_hubloc = $hub;
}
if ($hub['hubloc_network'] === 'zot6') {
Libzot::update_cached_hubloc($hub);
}
}
}
if ($ap_hubloc) {
// we already have a stored record. Determine if it needs updating.
if ($ap_hubloc['hubloc_updated'] < datetime_convert('UTC', 'UTC', ' now - 3 days') || $force) {
$person_obj = self::fetch($url);
}
else {
return;
}
}
if (isset($person_obj['id'])) {
$url = $person_obj['id'];
}
if (!$url) {
return;
}
$inbox = $person_obj['inbox'];
@@ -1545,21 +1646,48 @@ class Activity {
return;
}
$name = $person_obj['name'];
if (!$name)
$name = $person_obj['preferredUsername'];
if (!$name)
$name = t('Unknown');
// store the actor record in XConfig
XConfig::Set($url, 'system', 'actor_record', $person_obj);
$name = $person_obj['name'];
if (!$name) {
$name = $person_obj['preferredUsername'];
}
if (!$name) {
$name = t('Unknown');
}
$webfinger_addr = '';
$m = parse_url($url);
if ($m) {
$hostname = $m['host'];
$baseurl = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
$site_url = $m['scheme'] . '://' . $m['host'];
}
if (!empty($person_obj['preferredUsername']) && isset($parsed_url['host'])) {
$webfinger_addr = escape_tags($person_obj['preferredUsername']) . '@' . $hostname;
}
$icon = z_root() . '/' . get_default_profile_photo(300);
if ($person_obj['icon']) {
if (is_array($person_obj['icon'])) {
if (array_key_exists('url', $person_obj['icon']))
if (array_key_exists('url', $person_obj['icon'])) {
$icon = $person_obj['icon']['url'];
else
$icon = $person_obj['icon'][0]['url'];
}
else {
if (is_string($person_obj['icon'][0])) {
$icon = $person_obj['icon'][0];
}
elseif (array_key_exists('url', $person_obj['icon'][0])) {
$icon = $person_obj['icon'][0]['url'];
}
}
}
else
else {
$icon = $person_obj['icon'];
}
}
$links = false;
@@ -1592,20 +1720,6 @@ class Activity {
$profile = $url;
}
$collections = [];
if ($inbox) {
$collections['inbox'] = $inbox;
if (array_key_exists('outbox', $person_obj))
$collections['outbox'] = $person_obj['outbox'];
if (array_key_exists('followers', $person_obj))
$collections['followers'] = $person_obj['followers'];
if (array_key_exists('following', $person_obj))
$collections['following'] = $person_obj['following'];
if (array_key_exists('endpoints', $person_obj) && array_key_exists('sharedInbox', $person_obj['endpoints']))
$collections['sharedInbox'] = $person_obj['endpoints']['sharedInbox'];
}
if (array_key_exists('publicKey', $person_obj) && array_key_exists('publicKeyPem', $person_obj['publicKey'])) {
if ($person_obj['id'] === $person_obj['publicKey']['owner']) {
$pubkey = $person_obj['publicKey']['publicKeyPem'];
@@ -1615,84 +1729,89 @@ class Activity {
}
}
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
$r = q("select * from xchan join hubloc on xchan_hash = hubloc_hash where xchan_hash = '%s'",
dbesc($url)
);
if (!$r) {
if ($r) {
// Record exists. Cache existing records for one week at most
// then refetch to catch updated profile photos, names, etc.
$d = datetime_convert('UTC', 'UTC', 'now - 3 days');
if ($r[0]['hubloc_updated'] > $d && !$force) {
return;
}
q("UPDATE site SET site_update = '%s', site_dead = 0 WHERE site_url = '%s'",
dbesc(datetime_convert()),
dbesc($site_url)
);
// update existing xchan record
q("update xchan set xchan_name = '%s', xchan_guid = '%s', xchan_pubkey = '%s', xchan_addr = '%s', xchan_network = 'activitypub', xchan_name_date = '%s' where xchan_hash = '%s'",
dbesc(escape_tags($name)),
dbesc(escape_tags($url)),
dbesc(escape_tags($pubkey)),
dbesc(escape_tags($webfinger_addr)),
dbescdate(datetime_convert()),
dbesc($url)
);
// update existing hubloc record
q("update hubloc set hubloc_guid = '%s', hubloc_addr = '%s', hubloc_network = 'activitypub', hubloc_url = '%s', hubloc_host = '%s', hubloc_callback = '%s', hubloc_updated = '%s', hubloc_id_url = '%s' where hubloc_hash = '%s'",
dbesc(escape_tags($url)),
dbesc(escape_tags($webfinger_addr)),
dbesc(escape_tags($baseurl)),
dbesc(escape_tags($hostname)),
dbesc(escape_tags($inbox)),
dbescdate(datetime_convert()),
dbesc(escape_tags($profile)),
dbesc($url)
);
}
else {
// create a new record
xchan_store_lowlevel(
[
'xchan_hash' => $url,
'xchan_guid' => $url,
'xchan_pubkey' => $pubkey,
'xchan_addr' => '',
'xchan_url' => $profile,
'xchan_name' => $name,
'xchan_hash' => escape_tags($url),
'xchan_guid' => escape_tags($url),
'xchan_pubkey' => escape_tags($pubkey),
'xchan_addr' => $webfinger_addr,
'xchan_url' => escape_tags($profile),
'xchan_name' => escape_tags($name),
'xchan_name_date' => datetime_convert(),
'xchan_network' => 'activitypub'
]
);
}
else {
// Record exists. Cache existing records for one week at most
// then refetch to catch updated profile photos, names, etc.
$d = datetime_convert('UTC', 'UTC', 'now - 1 week');
if ($r[0]['xchan_name_date'] > $d)
return;
// update existing record
q("update xchan set xchan_name = '%s', xchan_pubkey = '%s', xchan_network = '%s', xchan_name_date = '%s' where xchan_hash = '%s'",
dbesc($name),
dbesc($pubkey),
dbesc('activitypub'),
dbesc(datetime_convert()),
dbesc($url)
);
}
if ($collections) {
set_xconfig($url, 'activitypub', 'collections', $collections);
}
$r = q("select * from hubloc where hubloc_hash = '%s' limit 1",
dbesc($url)
);
$m = parse_url($url);
if ($m) {
$hostname = $m['host'];
$site_url = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
}
if (!$r) {
hubloc_store_lowlevel(
[
'hubloc_guid' => $url,
'hubloc_hash' => $url,
'hubloc_addr' => '',
'hubloc_guid' => escape_tags($url),
'hubloc_hash' => escape_tags($url),
'hubloc_addr' => $webfinger_addr,
'hubloc_network' => 'activitypub',
'hubloc_url' => $site_url,
'hubloc_host' => $hostname,
'hubloc_callback' => $inbox,
'hubloc_url' => escape_tags($baseurl),
'hubloc_host' => escape_tags($hostname),
'hubloc_callback' => escape_tags($inbox),
'hubloc_updated' => datetime_convert(),
'hubloc_primary' => 1,
'hubloc_id_url' => $profile
'hubloc_id_url' => escape_tags($profile)
]
);
}
q("UPDATE site SET site_update = '%s', site_dead = 0 WHERE site_url = '%s' AND site_update < %s - INTERVAL %s",
dbesc(datetime_convert()),
dbesc($site_url),
db_utcnow(),
db_quoteinterval('1 DAY')
);
// We store all ActivityPub actors we can resolve. Some of them may be able to communicate over Zot6. Find them.
// Adding zot discovery urls to the actor record will cause federation to fail with the 20-30 projects which don't accept arrays in the url field.
if (!$icon)
$icon = z_root() . '/' . get_default_profile_photo(300);
$actor_protocols = self::get_actor_protocols($person_obj);
if (in_array('zot6', $actor_protocols)) {
$zx = q("select * from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6'",
dbesc($url)
);
if (!$zx && $webfinger_addr) {
Master::Summon(['Gprobe', bin2hex($webfinger_addr)]);
}
}
$photos = import_xchan_photo($icon, $url);
q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
@@ -1741,15 +1860,10 @@ class Activity {
static function create_note($channel, $observer_hash, $act) {
$s = [];
// Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field.
// They are hidden in the public timeline if the public inbox is listed in the 'cc' field.
// This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point.
$pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false);
$s = [];
$is_sys_channel = is_sys_channel($channel['channel_id']);
$parent = ((array_key_exists('inReplyTo', $act->obj)) ? urldecode($act->obj['inReplyTo']) : '');
$parent = ((array_key_exists('inReplyTo', $act->obj)) ? urldecode($act->obj['inReplyTo']) : '');
if ($parent) {
$r = q("select * from item where uid = %d and ( mid = '%s' or mid = '%s' ) limit 1",
@@ -1764,7 +1878,7 @@ class Activity {
}
if ($r[0]['owner_xchan'] === $channel['channel_hash']) {
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !($is_sys_channel && $pubstream)) {
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !$is_sys_channel) {
logger('no comment permission.');
return;
}
@@ -1776,13 +1890,28 @@ class Activity {
}
else {
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !($is_sys_channel && $pubstream)) {
logger('no permission');
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !$is_sys_channel) {
logger('no send_stream permission');
return;
}
$s['owner_xchan'] = $s['author_xchan'] = $observer_hash;
}
if ($act->recips && (!in_array(ACTIVITY_PUBLIC_INBOX, $act->recips)))
$s['item_private'] = 1;
if (array_key_exists('directMessage', $act->obj) && intval($act->obj['directMessage'])) {
$s['item_private'] = 2;
}
if (intval($s['item_private']) === 2) {
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'post_mail')) {
logger('no post_mail permission');
return;
}
}
$abook = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc($observer_hash),
intval($channel['channel_id'])
@@ -1931,14 +2060,6 @@ class Activity {
}
}
if ($act->recips && (!in_array(ACTIVITY_PUBLIC_INBOX, $act->recips)))
$s['item_private'] = 1;
if (array_key_exists('directMessage', $act->obj) && intval($act->obj['directMessage'])) {
$s['item_private'] = 2;
}
set_iconfig($s, 'activitypub', 'recips', $act->raw_recips);
if ($parent) {
set_iconfig($s, 'activitypub', 'rawmsg', $act->raw, 1);
@@ -2093,7 +2214,7 @@ class Activity {
// Unfollow is not defined by ActivityStreams, which prefers Undo->Follow.
// This may have to be revisited if AP projects start using Follow for objects other than actors.
if (in_array($act->type, [ 'Follow', 'Unfollow' ])) {
if (in_array($act->type, ['Follow', 'Unfollow'])) {
return false;
}
@@ -2116,10 +2237,12 @@ class Activity {
$s['parent_mid'] = $act->parent_id;
if (array_key_exists('published', $act->data)) {
$s['created'] = datetime_convert('UTC', 'UTC', $act->data['published']);
$s['created'] = datetime_convert('UTC', 'UTC', $act->data['published']);
$s['commented'] = $s['created'];
}
elseif (array_key_exists('published', $act->obj)) {
$s['created'] = datetime_convert('UTC', 'UTC', $act->obj['published']);
$s['created'] = datetime_convert('UTC', 'UTC', $act->obj['published']);
$s['commented'] = $s['created'];
}
if (array_key_exists('updated', $act->data)) {
$s['edited'] = datetime_convert('UTC', 'UTC', $act->data['updated']);
@@ -2190,10 +2313,10 @@ class Activity {
}
}
if (! array_key_exists('created', $s))
if (!array_key_exists('created', $s))
$s['created'] = datetime_convert();
if (! array_key_exists('edited', $s))
if (!array_key_exists('edited', $s))
$s['edited'] = $s['created'];
$s['title'] = (($response_activity) ? EMPTY_STR : self::bb_content($content, 'name'));
@@ -2268,7 +2391,6 @@ class Activity {
$s['app'] = escape_tags($generator['name']);
}
if (!$response_activity) {
$a = self::decode_taxonomy($act->obj);
if ($a) {
@@ -2403,7 +2525,7 @@ class Activity {
}
if ($act->obj['type'] === 'Image') {
if ($act->obj['type'] === 'Image' && strpos($s['body'], 'zrl=') === false) {
$ptr = null;
@@ -2545,12 +2667,6 @@ class Activity {
return;
}*/
// Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field.
// They are hidden in the public timeline if the public inbox is listed in the 'cc' field.
// This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point.
$pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false);
// TODO: this his handled in pubcrawl atm.
// very unpleasant and imperfect way of determining a Mastodon DM
/*if ($act->raw_recips && array_key_exists('to',$act->raw_recips) && is_array($act->raw_recips['to']) && count($act->raw_recips['to']) === 1 && $act->raw_recips['to'][0] === channel_url($channel) && ! $act->raw_recips['cc']) {
@@ -2611,7 +2727,7 @@ class Activity {
$allowed = true;
// reject public stream comments that weren't sent by the conversation owner
if ($is_sys_channel && $pubstream && $item['owner_xchan'] !== $observer_hash && !$fetch_parents) {
if ($is_sys_channel && $item['owner_xchan'] !== $observer_hash && !$fetch_parents) {
$allowed = false;
}
}
@@ -2626,7 +2742,7 @@ class Activity {
// The $item['item_fetched'] flag is set in fetch_and_store_parents().
// In this case we should check against author permissions because sender is not owner.
if (perm_is_allowed($channel['channel_id'], (($item['item_fetched']) ? $item['author_xchan'] : $observer_hash), 'send_stream') || ($is_sys_channel && $pubstream)) {
if (perm_is_allowed($channel['channel_id'], (($item['item_fetched']) ? $item['author_xchan'] : $observer_hash), 'send_stream') || $is_sys_channel) {
$allowed = true;
}
// TODO: not implemented
@@ -2641,6 +2757,11 @@ class Activity {
$allowed = true;
}
if (intval($item['item_private']) === 2) {
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'post_mail')) {
$allowed = false;
}
}
if ($is_sys_channel) {
@@ -2764,7 +2885,7 @@ class Activity {
$fetch = false;
// TODO: debug
// if (perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') && (PConfig::Get($channel['channel_id'],'system','hyperdrive',true) || $act->type === 'Announce')) {
if (perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') || ($is_sys_channel && $pubstream)) {
if (perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') || $is_sys_channel) {
$fetch = (($fetch_parents) ? self::fetch_and_store_parents($channel, $observer_hash, $item, $force) : false);
}
if ($fetch) {
@@ -3072,16 +3193,10 @@ class Activity {
static function announce_note($channel, $observer_hash, $act) {
$s = [];
$s = [];
$is_sys_channel = is_sys_channel($channel['channel_id']);
// Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field.
// They are hidden in the public timeline if the public inbox is listed in the 'cc' field.
// This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point.
$pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false);
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !($is_sys_channel && $pubstream)) {
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !$is_sys_channel) {
logger('no permission');
return;
}
@@ -3338,7 +3453,7 @@ class Activity {
$ret = false;
foreach ($attach as $a) {
if (array_key_exists('type',$a) && stripos($a['type'], 'image') !== false) {
if (array_key_exists('type', $a) && stripos($a['type'], 'image') !== false) {
if (self::media_not_in_body($a['href'], $body)) {
$ret .= "\n\n" . '[img]' . $a['href'] . '[/img]';
}
@@ -3496,7 +3611,7 @@ class Activity {
static function find_best_identity($xchan) {
if (filter_var($xchan, FILTER_VALIDATE_URL)) {
$r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' and hubloc_network in ('zot6', 'zot') and hubloc_deleted = 0",
$r = q("SELECT hubloc_hash, hubloc_network FROM hubloc WHERE hubloc_id_url = '%s' AND hubloc_network IN ('zot6', 'activitypub') AND hubloc_deleted = 0",
dbesc($xchan)
);
if ($r) {
@@ -3510,4 +3625,85 @@ class Activity {
}
static function get_cached_actor($id) {
$actor = XConfig::Get($id, 'system', 'actor_record');
if ($actor) {
return $actor;
}
// try other get_cached_actor providers (e.g. diaspora)
$hookdata = [
'id' => $id,
'actor' => false
];
call_hooks('get_cached_actor_provider', $hookdata);
return $hookdata['actor'];
}
static function get_actor_hublocs($url, $options = 'all') {
switch ($options) {
case 'activitypub':
$hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_hash = '%s' and hubloc_deleted = 0 ",
dbesc($url)
);
break;
case 'zot6':
$hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_id_url = '%s' and hubloc_deleted = 0 ",
dbesc($url)
);
break;
case 'all':
default:
$hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where ( hubloc_id_url = '%s' OR hubloc_hash = '%s' ) and hubloc_deleted = 0 ",
dbesc($url),
dbesc($url)
);
break;
}
return $hublocs;
}
static function get_actor_collections($url) {
$ret = [];
$actor_record = XConfig::Get($url, 'system', 'actor_record');
if (!$actor_record) {
return $ret;
}
foreach (['inbox', 'outbox', 'followers', 'following'] as $collection) {
if (isset($actor_record[$collection]) && $actor_record[$collection]) {
$ret[$collection] = $actor_record[$collection];
}
}
if (array_path_exists('endpoints/sharedInbox', $actor_record) && $actor_record['endpoints']['sharedInbox']) {
$ret['sharedInbox'] = $actor_record['endpoints']['sharedInbox'];
}
return $ret;
}
static function get_actor_protocols($actor) {
$ret = [];
if (!array_key_exists('tag', $actor) || empty($actor['tag']) || !is_array($actor['tag'])) {
return $ret;
}
foreach ($tag as $t) {
if ((isset($t['type']) && $t['type'] === 'PropertyValue') &&
(isset($t['name']) && $t['name'] === 'Protocol') &&
(isset($t['value']) && in_array($t['value'], ['zot6', 'activitypub', 'diaspora']))
) {
$ret[] = $t['value'];
}
}
return $ret;
}
}

View File

@@ -300,16 +300,8 @@ class ActivityStreams {
function get_actor($property, $base = '', $namespace = '') {
$x = $this->get_property_obj($property, $base, $namespace);
if ($this->is_url($x)) {
// SECURITY: If we have already stored the actor profile, re-generate it
// from cached data - don't refetch it from the network
$r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
dbesc($x)
);
if ($r) {
$y = Activity::encode_person($r[0]);
$y['cached'] = true;
$y = Activity::get_cached_actor($x);
if ($y) {
return $y;
}
}

View File

@@ -2,7 +2,7 @@
namespace Zotlabs\Lib;
use Zotlabs\Lib\Libsync;
use App;
require_once('include/plugin.php');
require_once('include/channel.php');
@@ -21,9 +21,10 @@ class Apps {
* @brief
*
* @param boolean $translate (optional) default true
* @param boolean $sync (optional) default false used if called from sync_sysapps()
* @return array
*/
static public function get_system_apps($translate = true) {
static public function get_system_apps($translate = true, $sync = false) {
$ret = [];
if(is_dir('apps'))
@@ -33,7 +34,7 @@ class Apps {
if($files) {
foreach($files as $f) {
$x = self::parse_app_description($f,$translate);
$x = self::parse_app_description($f, $translate, $sync);
if($x) {
$ret[] = $x;
}
@@ -45,7 +46,7 @@ class Apps {
$path = explode('/',$f);
$plugin = trim($path[1]);
if(plugin_is_installed($plugin)) {
$x = self::parse_app_description($f,$translate);
$x = self::parse_app_description($f, $translate, $sync);
if($x) {
$x['plugin'] = $plugin;
$ret[] = $x;
@@ -76,7 +77,9 @@ class Apps {
'Directory',
'Search',
'Help',
'Profile Photo'
'Profile Photo',
'HQ',
'Post'
]);
/**
@@ -207,9 +210,10 @@ class Apps {
*
* @param string $f filename
* @param boolean $translate (optional) default true
* @param boolean $sync (optional) default false
* @return boolean|array
*/
static public function parse_app_description($f, $translate = true) {
static public function parse_app_description($f, $translate = true, $sync = false) {
$ret = [];
$matches = [];
@@ -255,7 +259,7 @@ class Apps {
if(array_key_exists('categories',$ret))
$ret['categories'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['categories']);
if(array_key_exists('requires',$ret)) {
if(array_key_exists('requires',$ret) && !$sync) {
$requires = explode(',',$ret['requires']);
foreach($requires as $require) {
$require = trim(strtolower($require));
@@ -307,14 +311,16 @@ class Apps {
}
}
}
if(isset($ret)) {
if($translate)
self::translate_system_apps($ret);
return $ret;
if(empty($ret)) {
return false;
}
return false;
if($translate) {
self::translate_system_apps($ret);
}
return $ret;
}
@@ -374,7 +380,7 @@ class Apps {
'Permission Categories' => t('Permission Categories'),
'Public Stream' => t('Public Stream'),
'My Chatrooms' => t('My Chatrooms'),
'Channel Export' => t('Channel Export')
'Channel Export' => t('Channel Export'),
);
if(array_key_exists('name',$arr)) {
@@ -524,7 +530,7 @@ class Apps {
}
elseif(remote_channel()) {
$observer = \App::get_observer();
if($observer && in_array($observer['xchan_network'], ['zot6', 'zot'])) {
if($observer && $observer['xchan_network'] === 'zot6') {
// some folks might have xchan_url redirected offsite, use the connurl
$x = parse_url($observer['xchan_connurl']);
if($x) {
@@ -536,13 +542,47 @@ class Apps {
$install_action = (($installed) ? t('Update') : t('Install'));
$icon = ((strpos($papp['photo'],'icon:') === 0) ? substr($papp['photo'],5) : '');
if (!$installed && $mode === 'module') {
$_SESSION['return_url'] = App::$query_string;
return replace_macros(get_markup_template('app_install.tpl'), [
'$papp' => $papp,
'$install' => $install_action
]);
}
if($mode === 'navbar') {
return replace_macros(get_markup_template('app_nav_pinned.tpl'),array(
'$app' => $papp,
'$icon' => $icon,
));
}
if($mode === 'nav') {
return replace_macros(get_markup_template('app_nav.tpl'),array(
'$app' => $papp,
'$icon' => $icon,
));
}
if($mode === 'inline') {
return replace_macros(get_markup_template('app_inline.tpl'),array(
'$app' => $papp,
'$icon' => $icon,
'$installed' => $installed,
'$purchase' => ((isset($papp['page']) && (! $installed)) ? t('Purchase') : ''),
'$action_label' => $install_action
));
}
if(in_array($mode, ['nav-order', 'nav-order-pinned'])) {
return replace_macros(get_markup_template('app_order.tpl'),array(
'$app' => $papp,
'$icon' => $icon,
'$hosturl' => $hosturl,
'$mode' => $mode
));
}
if($mode === 'install') {
$papp['embed'] = true;
}
@@ -563,8 +603,6 @@ class Apps {
'$pin' => ((isset($papp['embed']) || $mode == 'edit') ? false : true),
'$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true),
'$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true),
'$navapps' => (($mode == 'nav') ? true : false),
'$order' => (($mode === 'nav-order' || $mode === 'nav-order-pinned') ? true : false),
'$mode' => $mode,
'$add' => t('Add to app-tray'),
'$remove' => t('Remove from app-tray'),
@@ -574,6 +612,7 @@ class Apps {
));
}
static public function app_install($uid,$app) {
if(! is_array($app)) {
@@ -588,10 +627,12 @@ class Apps {
$app['uid'] = $uid;
if(self::app_installed($uid,$app,true))
if(self::app_installed($uid,$app,true)) {
$x = self::app_update($app);
else
}
else {
$x = self::app_store($app);
}
if($x['success']) {
$r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
@@ -599,13 +640,12 @@ class Apps {
intval($uid)
);
if($r) {
if(($app['uid']) && (! $r[0]['app_system'])) {
if($app['uid']) {
if($app['categories'] && (! $app['term'])) {
$r[0]['term'] = q("select * from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($r[0]['id'])
);
Libsync::build_sync_packet($uid,array('app' => $r[0]));
}
}
}
@@ -634,6 +674,7 @@ class Apps {
}
}
}
return true;
}
@@ -645,38 +686,35 @@ class Apps {
dbesc($app['guid']),
intval($uid)
);
if($x) {
if(! intval($x[0]['app_deleted'])) {
$x[0]['app_deleted'] = 1;
if(self::can_delete($uid,$app)) {
q("delete from app where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
q("delete from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($x[0]['id'])
);
/**
* @hooks app_destroy
* Called after app entry got removed from database
* and provide app array from database.
*/
call_hooks('app_destroy', $x[0]);
}
else {
q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
}
if(! intval($x[0]['app_system'])) {
Libsync::build_sync_packet($uid,array('app' => $x));
}
}
else {
self::app_undestroy($uid,$app);
}
if($x && intval($x[0]['app_deleted'])) {
self::app_undestroy($uid, $app);
return;
}
if(self::can_delete($uid,$app)) {
q("delete from app where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
q("delete from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($x[0]['id'])
);
/**
* @hooks app_destroy
* Called after app entry got removed from database
* and provide app array from database.
*/
call_hooks('app_destroy', $x[0]);
}
else {
q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
}
}
}
@@ -693,13 +731,11 @@ class Apps {
dbesc($app['guid']),
intval($uid)
);
if($x) {
if($x[0]['app_system']) {
q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
}
if($x && intval($x[0]['app_deleted']) && $x[0]['app_system']) {
q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
}
}
}
@@ -1158,9 +1194,9 @@ class Apps {
$y = explode(',',$arr['categories']);
if($y) {
foreach($y as $t) {
$t = trim($t);
$t = escape_tags(trim($t));
if($t) {
store_item_tag($darray['app_channel'],$x[0]['id'],TERM_OBJ_APP,TERM_CATEGORY,escape_tags($t),escape_tags(z_root() . '/apps/?f=&cat=' . escape_tags($t)));
store_item_tag($darray['app_channel'], $x[0]['id'], TERM_OBJ_APP, TERM_CATEGORY, $t, z_root() . '/apps/?f=&cat=' . $t);
}
}
}
@@ -1356,4 +1392,17 @@ class Apps {
return chunk_split(base64_encode(json_encode($papp)),72,"\n");
}
static public function get_papp($app) {
$r = q("select * from app where app_id = '%s' and app_channel = 0 limit 1",
dbesc(hash('whirlpool', $app))
);
if ($r) {
$papp = self::app_encode($r[0]);
return $papp;
}
return false;
}
}

View File

@@ -146,7 +146,7 @@ class Connect {
}
$allowed = ((in_array($xchan['xchan_network'],['rss','zot','zot6'])) ? 1 : 0);
$allowed = ((in_array($xchan['xchan_network'],['rss', 'zot6'])) ? 1 : 0);
$hookdata = ['channel_id' => $uid, 'follow_address' => $url, 'xchan' => $xchan, 'allowed' => $allowed, 'singleton' => 0];
call_hooks('follow_allow',$hookdata);

View File

@@ -87,8 +87,7 @@ class DReport {
// Is the sender one of our channels?
$c = q("select channel_id from channel where channel_hash = '%s' or channel_portable_id = '%s' limit 1",
dbesc($dr['sender']),
$c = q("select channel_id from channel where channel_hash = '%s' limit 1",
dbesc($dr['sender'])
);

View File

@@ -69,24 +69,24 @@ class Enotify {
$sender_name = $product;
$hostname = \App::get_hostname();
if(strpos($hostname,':'))
$hostname = substr($hostname,0,strpos($hostname,':'));
$hostname = substr($hostname, 0, strpos($hostname,':'));
// Do not translate 'noreply' as it must be a legal 7-bit email address
$reply_email = get_config('system','reply_address');
$reply_email = get_config('system', 'reply_address');
if(! $reply_email)
$reply_email = 'noreply' . '@' . $hostname;
$sender_email = get_config('system','from_email');
$sender_email = get_config('system', 'from_email');
if(! $sender_email)
$sender_email = 'Administrator' . '@' . $hostname;
$sender_name = get_config('system','from_email_name');
$sender_name = get_config('system', 'from_email_name');
if(! $sender_name)
$sender_name = \Zotlabs\Lib\System::get_site_name();
$additional_mail_header = "";
$additional_mail_header = '';
if(array_key_exists('item', $params)) {
require_once('include/conversation.php');
@@ -114,27 +114,28 @@ class Enotify {
}
$always_show_in_notices = get_pconfig($recip['channel_id'],'system','always_show_in_notices');
$vnotify = get_pconfig($recip['channel_id'],'system','vnotify');
$always_show_in_notices = get_pconfig($recip['channel_id'], 'system', 'always_show_in_notices');
$vnotify = get_pconfig($recip['channel_id'], 'system', 'vnotify');
$salutation = $recip['channel_name'];
// e.g. "your post", "David's photo", etc.
$possess_desc = t('%s <!item_type!>');
// @@TODO: consider using switch instead of those elseif
if ($params['type'] == NOTIFY_MAIL) {
logger('notification: mail');
$subject = sprintf( t('[$Projectname:Notify] New mail received at %s'),$sitename);
$subject = sprintf( t('[$Projectname:Notify] New direct message received at %s'), $sitename);
$preamble = sprintf( t('%1$s sent you a new private message at %2$s.'), $sender['xchan_name'],$sitename);
$epreamble = sprintf( t('%1$s sent you %2$s.'),'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a private message') . '[/zrl]');
$sitelink = t('Please visit %s to view and/or reply to your private messages.');
$tsitelink = sprintf( $sitelink, $siteurl . '/mail/' . $params['item']['id'] );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/mail/' . $params['item']['id'] . '">' . $sitename . '</a>');
$itemlink = $siteurl . '/mail/' . $params['item']['id'];
$preamble = sprintf( t('%1$s sent you a new direct message at %2$s'), $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s sent you %2$s.'), '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a direct message') . '[/zrl]');
$sitelink = t('Please visit %s to view and/or reply to your direct messages.');
$tsitelink = sprintf( $sitelink, $siteurl . '/hq/' . gen_link_id($params['item']['mid']));
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/hq/' . gen_link_id($params['item']['mid']) . '">' . $sitename . '</a>');
$itemlink = $siteurl . '/hq/' . gen_link_id($params['item']['mid']);
}
if ($params['type'] == NOTIFY_COMMENT) {
elseif ($params['type'] === NOTIFY_COMMENT) {
//logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
@@ -171,7 +172,6 @@ class Enotify {
// Check to see if there was already a notify for this post.
// If so don't create a second notification
$p = null;
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($params['link']),
intval($recip['channel_id'])
@@ -196,6 +196,7 @@ class Enotify {
xchan_query($p);
//@@FIXME $p can be null (line 188)
$item_post_type = item_post_type($p[0]);
// $private = $p[0]['item_private'];
$parent_id = $p[0]['id'];
@@ -237,7 +238,7 @@ class Enotify {
$subject = sprintf( t('[$Projectname:Notify] Moderated Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
else
$subject = sprintf( t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
$preamble = sprintf( t('%1$s commented on an item/conversation you have been following.'), $sender['xchan_name']);
$preamble = sprintf( t('%1$s commented on an item/conversation you have been following'), $sender['xchan_name']);
$epreamble = $dest_str;
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
@@ -250,7 +251,7 @@ class Enotify {
}
if ($params['type'] == NOTIFY_LIKE) {
elseif ($params['type'] === NOTIFY_LIKE) {
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$itemlink = $params['link'];
@@ -268,7 +269,6 @@ class Enotify {
// Check to see if there was already a notify for this post.
// If so don't create a second notification
$p = null;
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($params['link']),
intval($recip['channel_id'])
@@ -293,7 +293,7 @@ class Enotify {
xchan_query($p);
//@@FIXME $p can be null (line 285)
$item_post_type = item_post_type($p[0]);
// $private = $p[0]['item_private'];
$parent_id = $p[0]['id'];
@@ -302,7 +302,7 @@ class Enotify {
// "your post"
if($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
if($p[0]['owner']['xchan_name'] === $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
$dest_str = sprintf(t('%1$s liked [zrl=%2$s]your %3$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$itemlink,
@@ -318,7 +318,7 @@ class Enotify {
// differents subjects for messages on the same thread.
$subject = sprintf( t('[$Projectname:Notify] Like received to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
$preamble = sprintf( t('%1$s liked an item/conversation you created.'), $sender['xchan_name']);
$preamble = sprintf( t('%1$s liked an item/conversation you created'), $sender['xchan_name']);
$epreamble = $dest_str;
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
@@ -328,7 +328,7 @@ class Enotify {
if($params['type'] == NOTIFY_WALL) {
elseif($params['type'] === NOTIFY_WALL) {
$subject = sprintf( t('[$Projectname:Notify] %s posted to your profile wall') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s posted to your profile wall at %2$s') , $sender['xchan_name'], $sitename);
@@ -343,9 +343,8 @@ class Enotify {
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_TAGSELF) {
elseif ($params['type'] === NOTIFY_TAGSELF) {
$p = null;
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($params['link']),
intval($recip['channel_id'])
@@ -368,7 +367,7 @@ class Enotify {
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_POKE) {
elseif ($params['type'] === NOTIFY_POKE) {
$subject = sprintf( t('[$Projectname:Notify] %1$s poked you') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s poked you at %2$s') , $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s [zrl=%2$s]poked you[/zrl].') ,
@@ -385,7 +384,7 @@ class Enotify {
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_TAGSHARE) {
elseif ($params['type'] === NOTIFY_TAGSHARE) {
$subject = sprintf( t('[$Projectname:Notify] %s tagged your post') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s tagged your post at %2$s'),$sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s tagged [zrl=%2$s]your post[/zrl]') ,
@@ -398,7 +397,7 @@ class Enotify {
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_INTRO) {
elseif ($params['type'] === NOTIFY_INTRO) {
$subject = sprintf( t('[$Projectname:Notify] Introduction received'));
$preamble = sprintf( t('You\'ve received an new connection request from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a new connection request[/zrl] from %2$s.'),
@@ -412,7 +411,7 @@ class Enotify {
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_SUGGEST) {
elseif ($params['type'] === NOTIFY_SUGGEST) {
$subject = sprintf( t('[$Projectname:Notify] Friend suggestion received'));
$preamble = sprintf( t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a friend suggestion[/zrl] for %2$s from %3$s.'),
@@ -430,11 +429,11 @@ class Enotify {
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_CONFIRM) {
elseif ($params['type'] === NOTIFY_CONFIRM) {
// ?
}
if ($params['type'] == NOTIFY_SYSTEM) {
elseif ($params['type'] === NOTIFY_SYSTEM) {
// ?
}
@@ -477,7 +476,7 @@ class Enotify {
} while ($dups === true);
$datarray = array();
$datarray = [];
$datarray['hash'] = $hash;
$datarray['sender_hash'] = $sender['xchan_hash'];
$datarray['xname'] = $sender['xchan_name'];
@@ -514,7 +513,7 @@ class Enotify {
// (probably would be better that way)
if (!$always_show_in_notices) {
if (($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) {
if (($params['type'] === NOTIFY_WALL) || ($params['type'] === NOTIFY_MAIL) || ($params['type'] === NOTIFY_INTRO)) {
$seen = 1;
}
}
@@ -550,12 +549,12 @@ class Enotify {
}
$itemlink = z_root() . '/notify/view/' . $notify_id;
$msg = str_replace('$itemlink',$itemlink,$epreamble);
$msg = str_replace('$itemlink', $itemlink, $epreamble);
// wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation
if ((\App::$language === 'en' || (! \App::$language)) && strpos($msg,', '))
$msg = substr($msg,strpos($msg,', ')+1);
$msg = substr($msg, strpos($msg,', ')+1);
$datarray['id'] = $notify_id;
$datarray['msg'] = $msg;
@@ -575,7 +574,7 @@ class Enotify {
logger('notification: sending notification email');
$hn = get_pconfig($recip['channel_id'],'system','email_notify_host');
$hn = get_pconfig($recip['channel_id'], 'system', 'email_notify_host');
if($hn && (! stristr(\App::get_hostname(),$hn))) {
// this isn't the email notification host
pop_lang();
@@ -584,7 +583,7 @@ class Enotify {
$textversion = strip_tags(html_entity_decode(bbcode(stripslashes(str_replace(array("\\r", "\\n"), array( "", "\n"), $body))),ENT_QUOTES,'UTF-8'));
$htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array("","<br />\n"),$body)));
$htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array('',"<br />\n"),$body)));
// use $_SESSION['zid_override'] to force zid() to use
@@ -601,7 +600,7 @@ class Enotify {
unset($_SESSION['zid_override']);
unset($_SESSION['zrl_override']);
$datarray = array();
$datarray = [];
$datarray['banner'] = $banner;
$datarray['product'] = $product;
$datarray['preamble'] = $preamble;
@@ -758,9 +757,9 @@ class Enotify {
$messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
// generate a mime boundary
$mimeBoundary = rand(0, 9) . "-"
.rand(100000000, 999999999) . "-"
.rand(100000000, 999999999) . "=:"
$mimeBoundary = rand(0, 9) . '-'
.rand(100000000, 999999999) . '-'
.rand(100000000, 999999999) . '=:'
.rand(10000, 99999);
// generate a multipart/alternative message header
@@ -768,7 +767,7 @@ class Enotify {
$params['additionalMailHeader'] .
"From: $fromName <{$params['fromEmail']}>" . PHP_EOL .
"Reply-To: $fromName <{$params['replyTo']}>" . PHP_EOL .
"MIME-Version: 1.0" . PHP_EOL .
'MIME-Version: 1.0' . PHP_EOL .
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
// assemble the final multipart message body with the text and html types included
@@ -776,15 +775,15 @@ class Enotify {
$htmlBody = chunk_split(base64_encode($params['htmlVersion']));
$multipartMessageBody =
"--" . $mimeBoundary . PHP_EOL . // plain text section
"Content-Type: text/plain; charset=UTF-8" . PHP_EOL .
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
'--' . $mimeBoundary . PHP_EOL . // plain text section
'Content-Type: text/plain; charset=UTF-8' . PHP_EOL .
'Content-Transfer-Encoding: base64' . PHP_EOL . PHP_EOL .
$textBody . PHP_EOL .
"--" . $mimeBoundary . PHP_EOL . // text/html section
"Content-Type: text/html; charset=UTF-8" . PHP_EOL .
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
'--' . $mimeBoundary . PHP_EOL . // text/html section
'Content-Type: text/html; charset=UTF-8' . PHP_EOL .
'Content-Transfer-Encoding: base64' . PHP_EOL . PHP_EOL .
$htmlBody . PHP_EOL .
"--" . $mimeBoundary . "--" . PHP_EOL; // message ending
'--' . $mimeBoundary . '--' . PHP_EOL; // message ending
// send the message
$res = mail(
@@ -793,7 +792,7 @@ class Enotify {
$multipartMessageBody, // message body
$messageHeader // message headers
);
logger("notification: enotify::send returns " . (($res) ? 'success' : 'failure'), LOGGER_DEBUG);
logger('notification: enotify::send returns ' . (($res) ? 'success' : 'failure'), LOGGER_DEBUG);
return $res;
}
@@ -833,13 +832,12 @@ class Enotify {
$edit = false;
if($item['edited'] > $item['created']) {
$edit = true;
if($item['item_thread_top']) {
$itemem_text = sprintf( t('edited a post dated %s'), relative_date($item['created']));
$edit = true;
}
else {
$itemem_text = sprintf( t('edited a comment dated %s'), relative_date($item['created']));
$edit = true;
}
}
@@ -856,18 +854,18 @@ class Enotify {
'photo' => $item[$who]['xchan_photo_s'],
'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' => (($item['mid']) ? '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'])),
'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? gen_link_id($item['thr_parent']) : gen_link_id($item['mid'])),
'thread_top' => (($item['item_thread_top']) ? true : false),
'message' => bbcode(escape_tags($itemem_text)),
'body' => htmlentities(html2plain(bbcode($item['body']), 75, true), ENT_QUOTES, 'UTF-8', false),
'body' => htmlentities(html2plain(bbcode($item['body'], ['drop_media', true]), 75, true), ENT_QUOTES, 'UTF-8', false),
// these are for the superblock addon
'hash' => $item[$who]['xchan_hash'],
'uid' => $item['uid'],
'display' => true
);
call_hooks('enotify_format',$x);
call_hooks('enotify_format', $x);
if(! $x['display']) {
return [];
}
@@ -884,9 +882,9 @@ class Enotify {
$mid = basename($tt['link']);
$b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : 'b64.' . base64url_encode($mid));
$b64mid = gen_link_id($mid);
$x = [
'notify_link' => z_root() . '/notify/view/' . $tt['id'],
'notify_link' => (($tt['ntype'] === NOTIFY_MAIL) ? $tt['link'] : z_root() . '/notify/view/' . $tt['id']),
'name' => $tt['xname'],
'url' => $tt['url'],
'photo' => $tt['photo'],
@@ -903,7 +901,7 @@ class Enotify {
static public function format_intros($rr) {
$x = [
return [
'notify_link' => z_root() . '/connections/ifpending',
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
@@ -914,13 +912,11 @@ class Enotify {
'message' => t('added your channel')
];
return $x;
}
static public function format_files($rr) {
$x = [
return [
'notify_link' => z_root() . '/sharedwithme',
'name' => $rr['author']['xchan_name'],
'addr' => $rr['author']['xchan_addr'],
@@ -931,13 +927,11 @@ class Enotify {
'message' => t('shared a file with you')
];
return $x;
}
static public function format_mail($rr) {
$x = [
return [
'notify_link' => z_root() . '/mail/' . $rr['id'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
@@ -945,11 +939,9 @@ class Enotify {
'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'),
'message' => t('sent you a direct message'),
];
return $x;
}
static public function format_all_events($rr) {
@@ -959,7 +951,7 @@ class Enotify {
$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 = [
return [
'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
@@ -970,13 +962,12 @@ class Enotify {
'message' => t('created an event')
];
return $x;
}
static public function format_register($rr) {
$x = [
return [
'notify_link' => z_root() . '/admin/accounts',
'name' => $rr['reg_did2'],
//'addr' => '',
@@ -986,7 +977,5 @@ class Enotify {
'message' => t('status verified')
];
return $x;
}
}

View File

@@ -141,7 +141,6 @@ class Libsync {
logger('Packet: ' . print_r($info, true), LOGGER_DATA, LOG_DEBUG);
$total = count($synchubs);
foreach ($synchubs as $hub) {
$hash = random_string();
$n = Libzot::build_packet($channel, 'sync', $env_recips, json_encode($info), 'hz', $hub['hubloc_sitekey'], $hub['site_crypto']);
@@ -186,7 +185,6 @@ class Libsync {
require_once('include/import.php');
$result = [];
$keychange = ((array_key_exists('keychange', $arr)) ? true : false);
foreach ($deliveries as $d) {
@@ -246,6 +244,10 @@ class Libsync {
if (array_key_exists('app', $arr) && $arr['app'])
sync_apps($channel, $arr['app']);
if (array_key_exists('sysapp',$arr) && $arr['sysapp']) {
sync_sysapps($channel, $arr['sysapp']);
}
if (array_key_exists('addressbook', $arr) && $arr['addressbook'])
sync_addressbook($channel, $arr['addressbook']);
@@ -255,11 +257,8 @@ class Libsync {
if (array_key_exists('chatroom', $arr) && $arr['chatroom'])
sync_chatrooms($channel, $arr['chatroom']);
if (array_key_exists('conv', $arr) && $arr['conv'])
import_conv($channel, $arr['conv']);
if (array_key_exists('mail', $arr) && $arr['mail'])
sync_mail($channel, $arr['mail']);
//if (array_key_exists('mail', $arr) && $arr['mail'])
// sync_mail($channel, $arr['mail']);
if (array_key_exists('event', $arr) && $arr['event'])
sync_events($channel, $arr['event']);
@@ -273,8 +272,8 @@ class Libsync {
// deprecated, maintaining for a few months for upward compatibility
// this should sync webpages, but the logic is a bit subtle
if (array_key_exists('item_id', $arr) && $arr['item_id'])
sync_items($channel, $arr['item_id']);
//if (array_key_exists('item_id', $arr) && $arr['item_id'])
// sync_items($channel, $arr['item_id']);
if (array_key_exists('menu', $arr) && $arr['menu'])
sync_menus($channel, $arr['menu']);
@@ -707,6 +706,15 @@ class Libsync {
$ret = [];
// If a sender reports that the channel has been deleted, delete its hubloc
if (isset($arr['deleted_locally']) && intval($arr['deleted_locally'])) {
q("UPDATE hubloc SET hubloc_deleted = 1, hubloc_updated = '%s' WHERE hubloc_hash = '%s' AND hubloc_url = '%s'",
dbesc(datetime_convert()),
dbesc($sender['hash']),
dbesc($sender['site']['url'])
);
}
if ($arr['locations']) {
if ($absolute)
@@ -864,6 +872,7 @@ class Libsync {
$what .= 'delete_hub ';
$changed = true;
}
continue;
}

View File

@@ -266,7 +266,7 @@ class Libzot {
dbesc($them['xchan_addr'])
);
}
if (!$r) {
if (!$r && array_key_exists('xchan_hash', $them) && $them['xchan_hash']) {
$r = q("select hubloc_id_url, hubloc_primary from hubloc where hubloc_hash = '%s' order by hubloc_id desc",
dbesc($them['xchan_hash'])
);
@@ -275,8 +275,8 @@ class Libzot {
if ($r) {
foreach ($r as $rr) {
if (intval($rr['hubloc_primary'])) {
$url = $rr['hubloc_id_url'];
$record = $rr;
$url = $rr['hubloc_id_url'];
break;
}
}
if (!$url) {
@@ -284,13 +284,17 @@ class Libzot {
}
}
}
if (!$url) {
logger('zot_refresh: no url');
return false;
}
$m = parse_url($url);
$site_url = unparse_url([ 'scheme' => $m['scheme'], 'host' => $m['host'] ]);
$s = q("select site_dead from site where site_url = '%s' limit 1",
dbesc($url)
dbesc($site_url)
);
if ($s && intval($s[0]['site_dead']) && (!$force)) {
@@ -299,25 +303,25 @@ class Libzot {
}
$record = Zotfinger::exec($url, $channel);
// Check the HTTP signature
// Check the HTTP signature
$hsig = $record['signature'];
if ($hsig && $hsig['signer'] === $url && $hsig['header_valid'] === true && $hsig['content_valid'] === true)
if ($hsig && $hsig['signer'] === $url && $hsig['header_valid'] === true && $hsig['content_valid'] === true) {
$hsig_valid = true;
}
if (!$hsig_valid) {
logger('http signature not valid: ' . print_r($hsig, true));
return false;
}
logger('zot-info: ' . print_r($record, true), LOGGER_DATA, LOG_DEBUG);
$x = self::import_xchan($record['data'], (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
if (!$x['success'])
if (!$x['success']) {
return false;
}
if ($channel && $record['data']['permissions']) {
$permissions = explode(',', $record['data']['permissions']);
@@ -357,8 +361,9 @@ class Libzot {
// we have as we may have updated the year after sending a notification; and resetting
// to the one we just received would cause us to create duplicated events.
if (substr($r[0]['abook_dob'], 5) == substr($next_birthday, 5))
if (substr($r[0]['abook_dob'], 5) == substr($next_birthday, 5)) {
$next_birthday = $r[0]['abook_dob'];
}
$y = q("update abook set abook_dob = '%s'
where abook_xchan = '%s' and abook_channel = %d
@@ -368,17 +373,19 @@ class Libzot {
intval($channel['channel_id'])
);
if (!$y)
if (!$y) {
logger('abook update failed');
}
else {
// if we were just granted read stream permission and didn't have it before, try to pull in some posts
if ((!$old_read_stream_perm) && (intval($permissions['view_stream'])))
if (!$old_read_stream_perm && intval($permissions['view_stream'])) {
Master::Summon(['Onepoll', $r[0]['abook_id']]);
}
}
}
else {
$p = Permissions::connect_perms($channel['channel_id']);
$p = Permissions::connect_perms($channel['channel_id']);
$my_perms = $p['perms'];
$automatic = $p['automatic'];
@@ -419,8 +426,10 @@ class Libzot {
);
if ($new_connection) {
if (!Permissions::PermsCompare($new_perms, $previous_perms))
if (!Permissions::PermsCompare($new_perms, $previous_perms)) {
Master::Summon(['Notifier', 'permission_create', $new_connection[0]['abook_id']]);
}
Enotify::submit(
[
'type' => NOTIFY_INTRO,
@@ -432,40 +441,47 @@ class Libzot {
if (intval($permissions['view_stream'])) {
if (intval(get_pconfig($channel['channel_id'], 'perm_limits', 'send_stream') & PERMS_PENDING)
|| (!intval($new_connection[0]['abook_pending'])))
|| (!intval($new_connection[0]['abook_pending']))) {
Master::Summon(['Onepoll', $new_connection[0]['abook_id']]);
}
}
// If there is a default group for this channel, add this connection to it
// for pending connections this will happens at acceptance time.
// for pending connections this will happen at acceptance time.
if (!intval($new_connection[0]['abook_pending'])) {
$default_group = $channel['channel_default_group'];
if ($default_group) {
$g = Group::rec_byhash($channel['channel_id'], $default_group);
if ($g)
if ($g) {
Group::member_add($channel['channel_id'], '', $x['hash'], $g['id']);
}
}
}
unset($new_connection[0]['abook_id']);
unset($new_connection[0]['abook_account']);
unset($new_connection[0]['abook_channel']);
$abconfig = load_abconfig($channel['channel_id'], $new_connection['abook_xchan']);
if ($abconfig)
if ($abconfig) {
$new_connection['abconfig'] = $abconfig;
}
Libsync::build_sync_packet($channel['channel_id'], ['abook' => $new_connection]);
}
}
}
return true;
}
return false;
}
/**
* @brief Look up if channel is known and previously verified.
*
@@ -479,6 +495,7 @@ class Libzot {
* * \e string \b id_sig => id signed with conversant's private key
* * \e string \b location => URL of the origination hub of this communication
* * \e string \b location_sig => URL signed with conversant's private key
* * \e string \b site_id => URL signed with conversant's private key
* @param boolean $multiple (optional) default false
*
* @return array|null
@@ -488,7 +505,7 @@ class Libzot {
static function gethub($arr, $multiple = false) {
if ($arr['id'] && $arr['id_sig'] && $arr['location'] && $arr['location_sig']) {
if ($arr['id'] && $arr['id_sig'] && $arr['location'] && $arr['location_sig'] && $arr['site_id']) {
if (!check_siteallowed($arr['location'])) {
logger('blacklisted site: ' . $arr['location']);
@@ -512,9 +529,9 @@ class Libzot {
logger('Found', LOGGER_DEBUG);
return (($multiple) ? $r : $r[0]);
}
logger('Not found: ' . print_r($arr, true), LOGGER_DEBUG);
}
logger('Not found: ' . print_r($arr, true), LOGGER_DEBUG);
logger('Incomplete array: ' . print_r($arr, true), LOGGER_DEBUG);
return false;
}
@@ -616,7 +633,6 @@ class Libzot {
*/
static function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
/**
* @hooks import_xchan
* Called when processing the result of zot_finger() to store the result
@@ -666,6 +682,7 @@ class Libzot {
$arr['connect_url'] = '';
if ($r) {
if ($arr['photo'] && array_key_exists('updated', $arr['photo']) && $arr['photo']['updated'] > $r[0]['xchan_photo_date'])
$import_photos = true;
@@ -1142,6 +1159,7 @@ class Libzot {
}
$deliveries = null;
if (array_key_exists('recipients', $env) && count($env['recipients'])) {
@@ -1199,31 +1217,41 @@ class Libzot {
if (in_array($env['type'], ['activity', 'response'])) {
$r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' ",
if(!isset($AS->actor['id'])) {
logger('No actor id!');
return;
}
$r = q("select hubloc_hash, hubloc_network, hubloc_url from hubloc where hubloc_id_url = '%s'",
dbesc($AS->actor['id'])
);
if ($r) {
// selects a zot6 hash if available, otherwise use whatever we have
$r = self::zot_record_preferred($r);
$r = self::zot_record_preferred($r);
$arr['author_xchan'] = $r['hubloc_hash'];
}
if (!$arr['author_xchan']) {
if (! $arr['author_xchan']) {
logger('No author!');
return;
}
$s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
dbesc($env['sender'])
);
$arr['owner_xchan'] = $env['sender'];
// in individual delivery, change owner if needed
if ($s) {
$arr['owner_xchan'] = $s[0]['hubloc_hash'];
if(filter_var($env['sender'], FILTER_VALIDATE_URL)) {
// in individual delivery, change owner if needed
$s = q("select hubloc_hash, hubloc_url from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
dbesc($env['sender'])
);
if ($s) {
$arr['owner_xchan'] = $s[0]['hubloc_hash'];
}
}
else {
$arr['owner_xchan'] = $env['sender'];
if (! $arr['owner_xchan']) {
logger('No owner!');
return;
}
if ($private && (!intval($arr['item_private']))) {
@@ -1270,10 +1298,6 @@ class Libzot {
if ($AS->data['signed_data']) {
IConfig::Set($arr, 'activitypub', 'signed_data', $AS->data['signed_data'], false);
$j = json_decode($AS->data['signed_data'], true);
if ($j) {
IConfig::Set($arr, 'activitypub', 'rawmsg', json_encode(JSalmon::unpack($j['data'])), true);
}
}
logger('Activity received: ' . print_r($arr, true), LOGGER_DATA, LOG_DEBUG);
@@ -1332,7 +1356,7 @@ class Libzot {
static function find_parent($env, $act) {
if ($act) {
if (in_array($act->type, ['Like', 'Dislike'])) {
if (in_array($act->type, ['Like', 'Dislike']) && is_array($act->obj)) {
return $act->obj['id'];
}
if ($act->parent_id) {
@@ -1377,8 +1401,6 @@ class Libzot {
$check_mentions = true;
}
}
elseif ($msg['type'] === 'mail')
$perm = 'post_mail';
$r = [];
@@ -1464,10 +1486,11 @@ class Libzot {
* @param boolean $relay
* @param boolean $public (optional) default false
* @param boolean $request (optional) default false
* @param boolean $force (optional) default false - should only be set for manual fetch
* @return array
*/
static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false) {
static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false, $force = false) {
$result = [];
@@ -1569,7 +1592,7 @@ class Libzot {
if ((!$tag_delivery) && (!$local_public)) {
$allowed = (perm_is_allowed($channel['channel_id'], $sender, $perm));
if (!$allowed) {
if ((!$allowed) && $perm === 'post_comments') {
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
@@ -1595,7 +1618,7 @@ class Libzot {
// doesn't exist.
if ($perm === 'send_stream') {
if (get_pconfig($channel['channel_id'], 'system', 'hyperdrive', false) || $arr['verb'] === ACTIVITY_SHARE) {
if ($force || get_pconfig($channel['channel_id'], 'system', 'hyperdrive', false) || $arr['verb'] === ACTIVITY_SHARE) {
$allowed = true;
}
}
@@ -1606,6 +1629,12 @@ class Libzot {
$friendofriend = true;
}
if (intval($arr['item_private']) === 2) {
if (!perm_is_allowed($channel['channel_id'], $sender, 'post_mail')) {
$allowed = false;
}
}
if (!$allowed) {
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
$DR->update('permission denied');
@@ -1713,7 +1742,7 @@ class Libzot {
}
}
$ab = q("select * from abook where abook_channel = %d and abook_xchan = '%s'",
$ab = q("select * from abook where abook_channel = %d and abook_xchan = '%s'",
intval($channel['channel_id']),
dbesc($arr['owner_xchan'])
);
@@ -1864,7 +1893,7 @@ class Libzot {
return $result;
}
static public function fetch_conversation($channel, $mid) {
static public function fetch_conversation($channel, $mid, $force = false) {
// Use Zotfinger to create a signed request
@@ -1915,16 +1944,18 @@ class Libzot {
// logger($AS->debug());
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
$r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s'",
dbesc($AS->actor['id'])
);
$r = self::zot_record_preferred($r);
if (!$r) {
$y = import_author_xchan(['url' => $AS->actor['id']]);
if ($y) {
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
$r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s'",
dbesc($AS->actor['id'])
);
$r = self::zot_record_preferred($r);
}
if (!$r) {
logger('FOF Activity: no actor');
@@ -1940,9 +1971,8 @@ class Libzot {
}
}
if ($r) {
$arr['author_xchan'] = $r[0]['hubloc_hash'];
$arr['author_xchan'] = $r['hubloc_hash'];
}
if ($signer) {
@@ -1967,7 +1997,7 @@ class Libzot {
logger('FOF Activity received: ' . print_r($arr, true), LOGGER_DATA, LOG_DEBUG);
logger('FOF Activity recipient: ' . $channel['channel_hash'], LOGGER_DATA, LOG_DEBUG);
$result = self::process_delivery($arr['owner_xchan'], $AS, $arr, [$channel['channel_hash']], false, false, true);
$result = self::process_delivery($arr['owner_xchan'], $AS, $arr, [$channel['channel_hash']], false, false, true, $force);
if ($result) {
$ret = array_merge($ret, $result);
}
@@ -2210,90 +2240,6 @@ class Libzot {
return $post_id;
}
static function process_mail_delivery($sender, $arr, $deliveries) {
$result = [];
if ($sender != $arr['from_xchan']) {
logger('process_mail_delivery: sender is not mail author');
return;
}
foreach ($deliveries as $d) {
$DR = new DReport(z_root(), $sender, $d, $arr['mid']);
$r = q("select * from channel where channel_hash = '%s' limit 1",
dbesc($d['hash'])
);
if (!$r) {
$DR->update('recipient not found');
$result[] = $DR->get();
continue;
}
$channel = $r[0];
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
if (!perm_is_allowed($channel['channel_id'], $sender, 'post_mail')) {
/*
* Always allow somebody to reply if you initiated the conversation. It's anti-social
* and a bit rude to send a private message to somebody and block their ability to respond.
* If you are being harrassed and want to put an end to it, delete the conversation.
*/
$return = false;
if ($arr['parent_mid']) {
$return = q("select * from mail where mid = '%s' and channel_id = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
);
}
if (!$return) {
logger("permission denied for mail delivery {$channel['channel_id']}");
$DR->update('permission denied');
$result[] = $DR->get();
continue;
}
}
$r = q("select id from mail where mid = '%s' and channel_id = %d limit 1",
dbesc($arr['mid']),
intval($channel['channel_id'])
);
if ($r) {
if (intval($arr['mail_recalled'])) {
$x = q("delete from mail where id = %d and channel_id = %d",
intval($r[0]['id']),
intval($channel['channel_id'])
);
$DR->update('mail recalled');
$result[] = $DR->get();
logger('mail_recalled');
}
else {
$DR->update('duplicate mail received');
$result[] = $DR->get();
logger('duplicate mail received');
}
continue;
}
else {
$arr['account_id'] = $channel['channel_account_id'];
$arr['channel_id'] = $channel['channel_id'];
$item_id = mail_store($arr);
$DR->update('mail delivered');
$result[] = $DR->get();
}
}
return $result;
}
/**
* @brief Processes delivery of profile.
@@ -2664,29 +2610,34 @@ class Libzot {
// we may only end up with one; which results in posts with no author name or photo and are a bit
// of a hassle to repair. If either or both are missing, do a full discovery probe.
//if (!array_key_exists('id', $x)) {
//return import_author_activitypub($x);
//}
if(!isset($x['id']) && !isset($x['key']) && !isset($x['id_sig'])) {
return false;
}
$hash = self::make_xchan_hash($x['id'], $x['key']);
$desturl = $x['url'];
$found_primary = false;
$r1 = q("select hubloc_url, hubloc_updated, site_dead from hubloc left join site on
hubloc_url = site_url where hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_primary = 1 limit 1",
dbesc($x['id']),
dbesc($x['id_sig'])
);
if ($r1) {
$found_primary = true;
}
$r2 = q("select xchan_hash from xchan where xchan_guid = '%s' and xchan_guid_sig = '%s' limit 1",
dbesc($x['id']),
dbesc($x['id_sig'])
);
$site_dead = false;
$primary_dead = false;
if ($r1 && intval($r1[0]['site_dead'])) {
$site_dead = true;
$primary_dead = true;
}
// We have valid and somewhat fresh information. Always true if it is our own site.
@@ -2704,16 +2655,17 @@ class Libzot {
// cached entry and the identity is valid. It's just unreachable until they bring back their
// server from the grave or create another clone elsewhere.
if ($site_dead) {
logger('dead site - ignoring', LOGGER_DEBUG, LOG_INFO);
if ($primary_dead || ! $found_primary) {
logger('dead or unknown primary site - ignoring', LOGGER_DEBUG, LOG_INFO);
$r = q("select hubloc_id_url from hubloc left join site on hubloc_url = site_url
where hubloc_hash = '%s' and site_dead = 0",
dbesc($hash)
);
if ($r) {
logger('found another site that is not dead: ' . $r[0]['hubloc_url'], LOGGER_DEBUG, LOG_INFO);
$desturl = $r[0]['hubloc_url'];
logger('found another site that is not dead: ' . $r[0]['hubloc_id_url'], LOGGER_DEBUG, LOG_INFO);
$desturl = $r[0]['hubloc_id_url'];
}
else {
return $hash;
@@ -2821,7 +2773,6 @@ class Libzot {
}
$e = $r[0];
$id = $e['channel_id'];
$sys_channel = (intval($e['channel_system']) ? true : false);
@@ -2924,7 +2875,19 @@ class Libzot {
];
$ret['channel_role'] = get_pconfig($e['channel_id'], 'system', 'permissions_role', 'custom');
$ret['protocols'] = ['zot6', 'zot'];
$hookinfo = [
'channel_id' => $id,
'protocols' => ['zot6']
];
/**
* @hooks channel_protocols
* * \e int \b channel_id
* * \e array \b protocols
*/
call_hooks('channel_protocols', $hookinfo);
$ret['protocols'] = $hookinfo['protocols'];
$ret['searchable'] = $searchable;
$ret['adult_content'] = $adult_channel;
$ret['public_forum'] = $public_forum;
@@ -2935,8 +2898,9 @@ class Libzot {
if ($deleted)
$ret['deleted'] = $deleted;
if (intval($e['channel_removed']))
if (intval($e['channel_removed'])) {
$ret['deleted_locally'] = true;
}
// premium or other channel desiring some contact with potential followers before connecting.
// This is a template - %s will be replaced with the follow_url we discover for the return channel.
@@ -3219,14 +3183,15 @@ class Libzot {
return $v;
}
}
foreach ($arr as $v) {
if ($v[$check] === 'zot') {
return $v;
}
}
return $arr[0];
}
static function update_cached_hubloc($hubloc) {
if ($hubloc['hubloc_updated'] > datetime_convert('UTC','UTC','now - 1 week') || $hubloc['hubloc_url'] === z_root()) {
return;
}
self::refresh( [ 'hubloc_id_url' => $hubloc['hubloc_id_url'] ] );
}
}

View File

@@ -207,8 +207,6 @@ class Libzotdir {
);
}
// If there are no directory servers, setup the fallback master
/** @FIXME What to do if we're in a different realm? */
@@ -249,11 +247,12 @@ class Libzotdir {
$syncdate = (($rr['site_sync'] <= NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : ''));
if (! $x['success'])
continue;
$j = json_decode($x['body'],true);
if (!($j['transactions']) || ($j['ratings']))
if (!$j['transactions'])
continue;
q("update site set site_sync = '%s' where site_url = '%s'",
@@ -265,6 +264,11 @@ class Libzotdir {
if (is_array($j['transactions']) && count($j['transactions'])) {
foreach ($j['transactions'] as $t) {
if (empty($t['hash']) || empty($t['transaction_id']) || empty($t['address'])) {
continue;
}
$r = q("select * from updates where ud_guid = '%s' limit 1",
dbesc($t['transaction_id'])
);
@@ -319,6 +323,14 @@ class Libzotdir {
}
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
// This is a workaround for a missing xchan_updated column
// TODO: implement xchan_updated in the xchan table and update this column instead
if($zf['data']['primary_location']['address'] && $zf['data']['primary_location']['url']) {
q("UPDATE hubloc SET hubloc_updated = '%s' WHERE hubloc_id_url = '%s' AND hubloc_primary = 1",
dbesc(datetime_convert()),
dbesc($zf['data']['primary_location']['url'])
);
}
}
else {
q("update updates set ud_last = '%s' where ud_addr = '%s'",
@@ -345,7 +357,7 @@ class Libzotdir {
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
$p = q("select channel.channel_hash, channel_address, channel_timezone, channel_portable_id, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
$p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
intval($uid)
);
@@ -354,7 +366,6 @@ class Libzotdir {
if ($p) {
$hash = $p[0]['channel_hash'];
$legacy_hash = $p[0]['channel_portable_id'];
$profile['description'] = $p[0]['pdesc'];
$profile['birthday'] = $p[0]['dob'];
@@ -393,10 +404,9 @@ class Libzotdir {
);
if(intval($r[0]['xchan_hidden']) != $hidden) {
$r = q("update xchan set xchan_hidden = %d where xchan_hash in ('%s', '%s')",
$r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
intval($hidden),
dbesc($hash),
dbesc($legacy_hash)
dbesc($hash)
);
}
@@ -410,13 +420,11 @@ class Libzotdir {
}
else {
// they may have made it private
q("delete from xprof where xprof_hash in ('%s', '%s')",
dbesc($hash),
dbesc($legacy_hash)
q("delete from xprof where xprof_hash = '%s'",
dbesc($hash)
);
q("delete from xtag where xtag_hash in ('%s', '%s')",
dbesc($hash),
dbesc($legacy_hash)
q("delete from xtag where xtag_hash = '%s'",
dbesc($hash)
);
}
@@ -635,8 +643,13 @@ class Libzotdir {
$dirmode = intval(get_config('system', 'directory_mode'));
if($dirmode == DIRECTORY_MODE_NORMAL)
if($dirmode == DIRECTORY_MODE_NORMAL) {
return;
}
if (empty($hash) || empty($guid) || empty($addr)) {
return;
}
if($flags) {
q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
@@ -656,9 +669,4 @@ class Libzotdir {
}
}
}

View File

@@ -11,8 +11,6 @@ class MessageFilter {
require_once('include/html2plain.php');
unobscure($item);
$text = prepare_text($item['body'],$item['mimetype']);
$text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text);

View File

@@ -12,8 +12,8 @@ class NativeWiki {
public static function listwikis($channel, $observer_hash) {
$sql_extra = item_permissions_sql($channel['channel_id'], $observer_hash);
$wikis = q("SELECT * FROM item
WHERE resource_type = '%s' AND mid = parent_mid AND uid = %d AND item_deleted = 0 $sql_extra",
$wikis = q("SELECT * FROM item
WHERE resource_type = '%s' AND mid = parent_mid AND uid = %d AND item_deleted = 0 $sql_extra",
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
intval($channel['channel_id'])
);
@@ -49,7 +49,7 @@ class NativeWiki {
$mid = z_root() . '/item/' . $uuid;
$arr = array(); // Initialize the array of parameters for the post
$item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
$item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
$wiki_url = z_root() . '/wiki/' . $channel['channel_address'] . '/' . $wiki['urlName'];
$arr['aid'] = $channel['channel_account_id'];
$arr['uuid'] = $uuid;
@@ -61,8 +61,8 @@ class NativeWiki {
$arr['resource_id'] = $resource_id;
$arr['owner_xchan'] = $channel['channel_hash'];
$arr['author_xchan'] = $observer_hash;
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
$arr['llink'] = $arr['plink'];
$arr['plink'] = $mid;
$arr['llink'] = z_root() . '/display/' . gen_link_id($mid);
$arr['title'] = $wiki['htmlName']; // name of new wiki;
$arr['allow_cid'] = $ac['allow_cid'];
$arr['allow_gid'] = $ac['allow_gid'];
@@ -133,13 +133,13 @@ class NativeWiki {
// update acl for any existing wiki pages
q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d where resource_type = 'nwikipage' and resource_id = '%s'",
dbesc($item['allow_cid']),
dbesc($item['allow_gid']),
dbesc($item['deny_cid']),
dbesc($item['deny_gid']),
dbesc($item['item_private']),
dbesc($item['allow_cid']),
dbesc($item['allow_gid']),
dbesc($item['deny_cid']),
dbesc($item['deny_gid']),
dbesc($item['item_private']),
dbesc($arr['resource_id'])
);
);
if($update['item_id']) {
@@ -211,12 +211,12 @@ class NativeWiki {
public static function get_wiki($channel_id, $observer_hash, $resource_id) {
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
$item = q("SELECT * FROM item WHERE uid = %d AND resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0
$item = q("SELECT * FROM item WHERE uid = %d AND resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0
$sql_extra ORDER BY id LIMIT 1",
intval($channel_id),
intval($channel_id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
@@ -224,7 +224,7 @@ class NativeWiki {
return [ 'wiki' => null ];
}
else {
$w = $item[0]; // wiki item table record
// Get wiki metadata
$rawName = get_iconfig($w, 'wiki', 'rawName');
@@ -246,20 +246,20 @@ class NativeWiki {
public static function exists_by_name($uid, $urlName) {
$sql_extra = item_permissions_sql($uid);
$sql_extra = item_permissions_sql($uid);
$item = q("SELECT item.id, resource_id FROM item left join iconfig on iconfig.iid = item.id
WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d
AND item_deleted = 0 $sql_extra limit 1",
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
//dbesc(urldecode($urlName)),
$item = q("SELECT item.id, resource_id FROM item left join iconfig on iconfig.iid = item.id
WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d
AND item_deleted = 0 $sql_extra limit 1",
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
//dbesc(urldecode($urlName)),
dbesc(self::name_decode($urlName)),
intval($uid)
);
if($item) {
return array('id' => $item[0]['id'], 'resource_id' => $item[0]['resource_id']);
}
}
else {
return array('id' => null, 'resource_id' => null);
}
@@ -277,7 +277,7 @@ class NativeWiki {
$r = q("SELECT * FROM item WHERE uid = %d and resource_type = '%s' AND resource_id = '%s' $sql_extra LIMIT 1",
intval($owner_id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
@@ -285,8 +285,6 @@ class NativeWiki {
return array('read' => false, 'write' => false, 'success' => true);
}
else {
// TODO: Create a new permission setting for wiki analogous to webpages. Until
// then, use webpage permissions
$write = perm_is_allowed($owner_id, $observer_hash,'write_wiki');
return array('read' => true, 'write' => $write, 'success' => true);
}

View File

@@ -2,14 +2,15 @@
namespace Zotlabs\Lib;
use \Zotlabs\Lib as Zlib;
use App;
use Zotlabs\Access\PermissionLimits;
class NativeWikiPage {
static public function page_list($channel_id,$observer_hash, $resource_id) {
static public function page_list($channel_id, $observer_hash, $resource_id) {
// TODO: Create item table records for pages so that metadata like title can be applied
$w = Zlib\NativeWiki::get_wiki($channel_id,$observer_hash,$resource_id);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$pages[] = [
'resource_id' => '',
@@ -18,134 +19,149 @@ class NativeWikiPage {
'link_id' => 'id_wiki_home_0'
];
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
$sql_extra = item_permissions_sql($channel_id, $observer_hash);
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0
$sql_extra order by title asc",
dbesc($resource_id),
intval($channel_id)
);
if($r) {
if ($r) {
$x = [];
$y = [];
foreach($r as $rv) {
if(! in_array($rv['mid'],$x)) {
foreach ($r as $rv) {
if (!in_array($rv['mid'], $x)) {
$y[] = $rv;
$x[] = $rv['mid'];
}
}
$items = fetch_post_tags($y,true);
$items = fetch_post_tags($y, true);
foreach($items as $page_item) {
$title = get_iconfig($page_item['id'],'nwikipage','pagetitle',t('(No Title)'));
if(urldecode($title) !== 'Home') {
foreach ($items as $page_item) {
$title = get_iconfig($page_item['id'], 'nwikipage', 'pagetitle', t('(No Title)'));
if (urldecode($title) !== 'Home') {
$pages[] = [
'resource_id' => $resource_id,
'title' => escape_tags($title),
//'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))),
'url' => Zlib\NativeWiki::name_encode($title),
'url' => NativeWiki::name_encode($title),
'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $page_item['id']
];
}
}
}
return array('pages' => $pages, 'wiki' => $w);
return ['pages' => $pages, 'wiki' => $w];
}
static public function create_page($channel_id, $observer_hash, $name, $resource_id, $mimetype = 'text/bbcode') {
static public function create_page($channel, $observer_hash, $name, $resource_id, $mimetype = 'text/bbcode') {
logger('mimetype: ' . $mimetype);
if(! in_array($mimetype,[ 'text/markdown','text/bbcode','text/plain','text/html' ]))
if (!in_array($mimetype, ['text/markdown', 'text/bbcode', 'text/plain', 'text/html']))
$mimetype = 'text/markdown';
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$w = NativeWiki::get_wiki($channel['channel_id'], $observer_hash, $resource_id);
if (! $w['wiki']) {
return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
// backslashes won't work well in the javascript functions
$name = str_replace('\\','',$name);
$name = str_replace('\\', '', $name);
$uuid = new_uuid();
$mid = z_root() . '/item/' . $uuid;
// create an empty activity
$arr = [];
$arr['uid'] = $channel_id;
$arr['author_xchan'] = $observer_hash;
$arr['mimetype'] = $mimetype;
$arr['title'] = $name;
$arr['resource_type'] = 'nwikipage';
$arr['resource_id'] = $resource_id;
$arr['allow_cid'] = $w['wiki']['allow_cid'];
$arr['allow_gid'] = $w['wiki']['allow_gid'];
$arr['deny_cid'] = $w['wiki']['deny_cid'];
$arr['deny_gid'] = $w['wiki']['deny_gid'];
$arr['public_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel_id,'view_wiki'),true);
$arr = [];
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
$arr['mid'] = $mid;
$arr['parent_mid'] = $w['wiki']['mid'];
$arr['parent'] = $w['wiki']['parent'];
$arr['uuid'] = $uuid;
$arr['item_hidden'] = $w['wiki']['item_hidden'];
$arr['plink'] = $mid;
$arr['llink'] = z_root() . '/display/' . gen_link_id($mid);
$arr['author_xchan'] = $observer_hash;
$arr['mimetype'] = $mimetype;
$arr['title'] = $name;
$arr['resource_type'] = 'nwikipage';
$arr['resource_id'] = $resource_id;
$arr['allow_cid'] = $w['wiki']['allow_cid'];
$arr['allow_gid'] = $w['wiki']['allow_gid'];
$arr['deny_cid'] = $w['wiki']['deny_cid'];
$arr['deny_gid'] = $w['wiki']['deny_gid'];
$arr['item_private'] = $w['wiki']['item_private'];
$arr['item_wall'] = 1;
$arr['item_origin'] = 1;
$arr['item_thread_top'] = 1;
$arr['verb'] = ACTIVITY_CREATE;
$arr['obj_type'] = 'Document';
// TODO: add an object?
$arr['public_policy'] = map_scope(PermissionLimits::Get($channel['channel_id'], 'view_wiki'), true);
// We may wish to change this some day.
$arr['item_unpublished'] = 1;
set_iconfig($arr,'nwikipage','pagetitle',(($name) ? $name : t('(No Title)')),true);
set_iconfig($arr, 'nwikipage', 'pagetitle', (($name) ? $name : t('(No Title)')), true);
$p = item_store($arr, false, false);
$p = post_activity_item($arr, false, false);
if($p['item_id']) {
$page = [
if ($p['item_id']) {
$page = [
'rawName' => $name,
'htmlName' => escape_tags($name),
//'urlName' => urlencode($name),
'urlName' => Zlib\NativeWiki::name_encode($name)
//'urlName' => urlencode($name),
'urlName' => NativeWiki::name_encode($name)
];
return array('page' => $page, 'item_id' => $p['item_id'], 'item' => $p['activity'], 'wiki' => $w, 'message' => '', 'success' => true);
return ['page' => $page, 'item_id' => $p['item_id'], 'item' => $p['activity'], 'wiki' => $w, 'message' => '', 'success' => true];
}
return [ 'success' => false, 'message' => t('Wiki page create failed.') ];
return ['success' => false, 'message' => t('Wiki page create failed.')];
}
static public function rename_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$pageNewName = ((array_key_exists('pageNewName',$arr)) ? $arr['pageNewName'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$pageNewName = ((array_key_exists('pageNewName', $arr)) ? $arr['pageNewName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if(! $w['wiki']) {
return array('message' => t('Wiki not found.'), 'success' => false);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Wiki not found.'), 'success' => false];
}
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageNewName)
);
if($ic) {
return [ 'success' => false, 'message' => t('Destination name already exists') ];
if ($ic) {
return ['success' => false, 'message' => t('Destination name already exists')];
}
$ids = [];
$ic = q("select *, item.id as item_id from iconfig left join item on iconfig.iid = item.id
$ic = q("select *, item.id as item_id from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if($ic) {
foreach($ic as $c) {
set_iconfig($c['item_id'],'nwikipage','pagetitle',$pageNewName);
if ($ic) {
foreach ($ic as $c) {
set_iconfig($c['item_id'], 'nwikipage', 'pagetitle', $pageNewName);
$ids[] = $c['item_id'];
}
@@ -154,105 +170,101 @@ class NativeWikiPage {
dbesc($pageNewName)
);
$page = [
'rawName' => $pageNewName,
'htmlName' => escape_tags($pageNewName),
$page = [
'rawName' => $pageNewName,
'htmlName' => escape_tags($pageNewName),
//'urlName' => urlencode(escape_tags($pageNewName))
'urlName' => Zlib\NativeWiki::name_encode($pageNewName)
'urlName' => NativeWiki::name_encode($pageNewName)
];
return [ 'success' => true, 'page' => $page ];
return ['success' => true, 'page' => $page];
}
return [ 'success' => false, 'message' => t('Page not found') ];
return ['success' => false, 'message' => t('Page not found')];
}
static public function get_page_content($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? intval($arr['channel_id']) : 0);
$revision = ((array_key_exists('revision',$arr)) ? intval($arr['revision']) : (-1));
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? intval($arr['channel_id']) : 0);
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (! $w['wiki']) {
return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$item = self::load_page($arr);
if($item) {
if ($item) {
$content = $item['body'];
return [
return [
'content' => $content,
'mimeType' => $w['mimeType'],
'pageMimeType' => $item['mimetype'],
'message' => '',
'pageMimeType' => $item['mimetype'],
'message' => '',
'success' => true
];
}
return array('content' => null, 'message' => t('Error reading page content'), 'success' => false);
return ['content' => null, 'message' => t('Error reading page content'), 'success' => false];
}
static public function page_history($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return array('history' => null, 'message' => 'Error reading wiki', 'success' => false);
return ['history' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$items = self::load_page_history($arr);
$history = [];
if($items) {
if ($items) {
$processed = 0;
foreach($items as $item) {
if($processed > 1000)
foreach ($items as $item) {
if ($processed > 1000)
break;
$processed ++;
$history[] = [
$processed++;
$history[] = [
'revision' => $item['revision'],
'date' => datetime_convert('UTC',date_default_timezone_get(),$item['edited']),
'name' => $item['author']['xchan_name'],
'title' => get_iconfig($item,'nwikipage','commit_msg')
'date' => datetime_convert('UTC', date_default_timezone_get(), $item['edited']),
'name' => $item['author']['xchan_name'],
'title' => get_iconfig($item, 'nwikipage', 'commit_msg')
];
}
return [ 'success' => true, 'history' => $history ];
return ['success' => true, 'history' => $history];
}
return [ 'success' => false ];
return ['success' => false];
}
static public function load_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
$revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : (-1));
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$revision = ((array_key_exists('revision', $arr)) ? $arr['revision'] : (-1));
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (! $w['wiki']) {
return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$ids = '';
@@ -262,32 +274,32 @@ class NativeWikiPage {
dbesc($pageUrlName)
);
if($ic) {
foreach($ic as $c) {
if($ids)
if ($ic) {
foreach ($ic as $c) {
if ($ids)
$ids .= ',';
$ids .= intval($c['iid']);
}
}
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
$sql_extra = item_permissions_sql($channel_id, $observer_hash);
if($revision == (-1))
if ($revision == (-1))
$sql_extra .= " order by revision desc ";
elseif($revision)
elseif ($revision)
$sql_extra .= " and revision = " . intval($revision) . " ";
$r = null;
if($ids) {
if ($ids) {
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) $sql_extra limit 1",
dbesc($resource_id),
intval($channel_id)
);
if($r) {
$items = fetch_post_tags($r,true);
if ($r) {
$items = fetch_post_tags($r, true);
return $items[0];
}
}
@@ -298,15 +310,14 @@ class NativeWikiPage {
static public function load_page_history($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
$revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : (-1));
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (! $w['wiki']) {
return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$ids = '';
@@ -315,28 +326,28 @@ class NativeWikiPage {
intval($channel_id),
dbesc($pageUrlName)
);
if($ic) {
foreach($ic as $c) {
if($ids)
if ($ic) {
foreach ($ic as $c) {
if ($ids)
$ids .= ',';
$ids .= intval($c['iid']);
}
}
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
$sql_extra = item_permissions_sql($channel_id, $observer_hash);
$sql_extra .= " order by revision desc ";
$r = null;
if($ids) {
if ($ids) {
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) and item_deleted = 0 $sql_extra",
dbesc($resource_id),
intval($channel_id)
);
if($r) {
if ($r) {
xchan_query($r);
$items = fetch_post_tags($r,true);
$items = fetch_post_tags($r, true);
return $items;
}
}
@@ -346,31 +357,30 @@ class NativeWikiPage {
static public function save_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$content = ((array_key_exists('content',$arr)) ? $arr['content'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
$revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : 0);
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$content = ((array_key_exists('content', $arr)) ? $arr['content'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return array('message' => t('Error reading wiki'), 'success' => false);
return ['message' => t('Error reading wiki'), 'success' => false];
}
// fetch the most recently saved revision.
// fetch the most recently saved revision.
$item = self::load_page($arr);
if(! $item) {
return array('message' => t('Page not found'), 'success' => false);
if (!$item) {
return ['message' => t('Page not found'), 'success' => false];
}
$mimetype = $item['mimetype'];
// change just the fields we need to change to create a revision;
// change just the fields we need to change to create a revision;
unset($item['id']);
unset($item['author']);
@@ -381,8 +391,8 @@ class NativeWikiPage {
$item['edited'] = datetime_convert();
$item['mimetype'] = $mimetype;
if($item['iconfig'] && is_array($item['iconfig']) && count($item['iconfig'])) {
for($x = 0; $x < count($item['iconfig']); $x ++) {
if ($item['iconfig'] && is_array($item['iconfig']) && count($item['iconfig'])) {
for ($x = 0; $x < count($item['iconfig']); $x++) {
unset($item['iconfig'][$x]['id']);
unset($item['iconfig'][$x]['iid']);
}
@@ -390,168 +400,164 @@ class NativeWikiPage {
$ret = item_store($item, false, false);
if($ret['item_id'])
return array('message' => '', 'item_id' => $ret['item_id'], 'filename' => $pageUrlName, 'success' => true);
if ($ret['item_id'])
return ['message' => '', 'item_id' => $ret['item_id'], 'filename' => $pageUrlName, 'success' => true];
else
return array('message' => t('Page update failed.'), 'success' => false);
}
return ['message' => t('Page update failed.'), 'success' => false];
}
static public function delete_page($arr) {
$pageUrlName = (array_key_exists('pageUrlName',$arr) ? $arr['pageUrlName'] : '');
$resource_id = (array_key_exists('resource_id',$arr) ? $arr['resource_id'] : '');
$observer_hash = (array_key_exists('observer_hash',$arr) ? $arr['observer_hash'] : '');
$channel_id = (array_key_exists('channel_id',$arr) ? $arr['channel_id'] : 0);
$pageUrlName = (array_key_exists('pageUrlName', $arr) ? $arr['pageUrlName'] : '');
$resource_id = (array_key_exists('resource_id', $arr) ? $arr['resource_id'] : '');
$observer_hash = (array_key_exists('observer_hash', $arr) ? $arr['observer_hash'] : '');
$channel_id = (array_key_exists('channel_id', $arr) ? $arr['channel_id'] : 0);
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if(! $w['wiki']) {
return [ 'success' => false, 'message' => t('Error reading wiki') ];
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['success' => false, 'message' => t('Error reading wiki')];
}
$ids = [];
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if($ic) {
foreach($ic as $c) {
if ($ic) {
foreach ($ic as $c) {
$ids[] = intval($c['iid']);
}
}
if($ids) {
if ($ids) {
drop_items($ids, true, DROPITEM_PHASE1);
return [ 'success' => true ];
return ['success' => true];
}
return [ 'success' => false, 'message' => t('Nothing deleted') ];
return ['success' => false, 'message' => t('Nothing deleted')];
}
static public function revert_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$commitHash = ((array_key_exists('commitHash',$arr)) ? $arr['commitHash'] : null);
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$commitHash = ((array_key_exists('commitHash', $arr)) ? $arr['commitHash'] : null);
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
if (! $commitHash) {
return array('message' => 'No commit was provided', 'success' => false);
if (!$commitHash) {
return ['message' => 'No commit was provided', 'success' => false];
}
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return array('message' => 'Error reading wiki', 'success' => false);
return ['message' => 'Error reading wiki', 'success' => false];
}
$x = $arr;
if(intval($commitHash) > 0) {
if (intval($commitHash) > 0) {
unset($x['commitHash']);
$x['revision'] = intval($commitHash) - 1;
$loaded = self::load_page($x);
$loaded = self::load_page($x);
if($loaded) {
if ($loaded) {
$content = $loaded['body'];
return [ 'content' => $content, 'success' => true ];
return ['content' => $content, 'success' => true];
}
return [ 'success' => false ];
return ['success' => false];
}
}
static public function compare_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$currentCommit = ((array_key_exists('currentCommit',$arr)) ? $arr['currentCommit'] : (-1));
$compareCommit = ((array_key_exists('compareCommit',$arr)) ? $arr['compareCommit'] : 0);
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$compareCommit = ((array_key_exists('compareCommit', $arr)) ? $arr['compareCommit'] : 0);
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return array('message' => t('Error reading wiki'), 'success' => false);
return ['message' => t('Error reading wiki'), 'success' => false];
}
$x = $arr;
$x = $arr;
$x['revision'] = (-1);
$currpage = self::load_page($x);
if($currpage)
if ($currpage)
$currentContent = $currpage['body'];
$x['revision'] = $compareCommit;
$comppage = self::load_page($x);
if($comppage)
$comppage = self::load_page($x);
if ($comppage)
$compareContent = $comppage['body'];
if($currpage && $comppage) {
if ($currpage && $comppage) {
require_once('library/class.Diff.php');
$diff = \Diff::toTable(\Diff::compare($currentContent, $compareContent));
return [ 'success' => true, 'diff' => $diff ];
return ['success' => true, 'diff' => $diff];
}
return [ 'success' => false, 'message' => t('Compare: object not found.') ];
return ['success' => false, 'message' => t('Compare: object not found.')];
}
static public function commit($arr) {
$commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : t('Page updated'));
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : t('Untitled'));
$commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : t('Page updated'));
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
if(array_key_exists('resource_id', $arr)) {
if (array_key_exists('resource_id', $arr)) {
$resource_id = $arr['resource_id'];
}
else {
return array('message' => t('Wiki resource_id required for git commit'), 'success' => false);
return ['message' => t('Wiki resource_id required for git commit'), 'success' => false];
}
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (! $w['wiki']) {
return array('message' => t('Error reading wiki'), 'success' => false);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Error reading wiki'), 'success' => false];
}
$page = self::load_page($arr);
if($page) {
set_iconfig($page['id'],'nwikipage','commit_msg',escape_tags($commit_msg),true);
return [ 'success' => true, 'item_id' => $page['id'], 'page' => $page ];
if ($page) {
set_iconfig($page['id'], 'nwikipage', 'commit_msg', escape_tags($commit_msg), true);
return ['success' => true, 'item_id' => $page['id'], 'page' => $page];
}
return [ 'success' => false, 'message' => t('Page not found.') ];
return ['success' => false, 'message' => t('Page not found.')];
}
static public function convert_links($s, $wikiURL) {
if (strpos($s,'[[') !== false) {
if (strpos($s, '[[') !== false) {
preg_match_all("/\[\[(.*?)\]\]/", $s, $match);
$pages = $pageURLs = array();
$pages = $pageURLs = [];
foreach ($match[1] as $m) {
// TODO: Why do we need to double urlencode for this to work?
//$pageURLs[] = urlencode(urlencode(escape_tags($m)));
$titleUri = explode('|',$m);
$page = $titleUri[0] ?? '';
$title = $titleUri[1] ?? $page;
$pageURLs[] = Zlib\NativeWiki::name_encode(escape_tags($page));
$pages[] = $title;
$titleUri = explode('|', $m);
$page = $titleUri[0] ?? '';
$title = $titleUri[1] ?? $page;
$pageURLs[] = NativeWiki::name_encode(escape_tags($page));
$pages[] = $title;
}
$idx = 0;
while(strpos($s,'[[') !== false) {
$replace = '<a href="'.$wikiURL.'/'.$pageURLs[$idx].'">'.$pages[$idx].'</a>';
$s = preg_replace("/\[\[(.*?)\]\]/", $replace, $s, 1);
while (strpos($s, '[[') !== false) {
$replace = '<a href="' . $wikiURL . '/' . $pageURLs[$idx] . '">' . $pages[$idx] . '</a>';
$s = preg_replace("/\[\[(.*?)\]\]/", $replace, $s, 1);
$idx++;
}
}
@@ -564,21 +570,21 @@ class NativeWikiPage {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$pageHistory = self::page_history([
'channel_id' => \App::$profile_uid,
'channel_id' => App::$profile_uid,
'observer_hash' => get_observer_hash(),
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName
]);
return replace_macros(get_markup_template('nwiki_page_history.tpl'), array(
return replace_macros(get_markup_template('nwiki_page_history.tpl'), [
'$pageHistory' => $pageHistory['history'],
'$permsWrite' => $arr['permsWrite'],
'$name_lbl' => t('Name'),
'$msg_label' => t('Message','wiki_history'),
'$msg_label' => t('Message', 'wiki_history'),
'$date_lbl' => t('Date'),
'$revert_btn' => t('Revert'),
'$compare_btn' => t('Compare')
));
]);
}
@@ -590,14 +596,14 @@ class NativeWikiPage {
* @return string
*/
static public function generate_toc($s) {
if (strpos($s,'[toc]') !== false) {
if (strpos($s, '[toc]') !== false) {
//$toc_md = wiki_toc($s); // Generate Markdown-formatted list prior to HTML render
$toc_md = '<ul id="wiki-toc"></ul>'; // use the available jQuery plugin http://ndabas.github.io/toc/
$s = preg_replace("/\[toc\]/", $toc_md, $s, -1);
$s = preg_replace("/\[toc\]/", $toc_md, $s, -1);
}
return $s;
}
/**
* Converts a select set of bbcode tags. Much of the code is copied from include/bbcode.php
@@ -605,27 +611,27 @@ class NativeWikiPage {
* @return string
*/
static public function bbcode($s) {
$s = str_replace(array('[baseurl]', '[sitename]'), array(z_root(), get_config('system', 'sitename')), $s);
$s = preg_replace_callback("/\[observer\.language\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_callback', $s);
$s = preg_replace_callback("/\[observer\.language\!\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_necallback', $s);
$s = str_replace(['[baseurl]', '[sitename]'], [z_root(), get_config('system', 'sitename')], $s);
$s = preg_replace_callback("/\[observer\.language\=(.*?)\](.*?)\[\/observer\]/ism", 'oblanguage_callback', $s);
$s = preg_replace_callback("/\[observer\.language\!\=(.*?)\](.*?)\[\/observer\]/ism", 'oblanguage_necallback', $s);
$observer = \App::get_observer();
$observer = App::get_observer();
if ($observer) {
$s1 = '<span class="bb_observer" title="' . t('Different viewers will see this text differently') . '">';
$s2 = '</span>';
$s1 = '<span class="bb_observer" title="' . t('Different viewers will see this text differently') . '">';
$s2 = '</span>';
$obsBaseURL = $observer['xchan_connurl'];
$obsBaseURL = preg_replace("/\/poco\/.*$/", '', $obsBaseURL);
$s = str_replace('[observer.baseurl]', $obsBaseURL, $s);
$s = str_replace('[observer.url]', $observer['xchan_url'], $s);
$s = str_replace('[observer.name]', $s1 . $observer['xchan_name'] . $s2, $s);
$s = str_replace('[observer.address]', $s1 . $observer['xchan_addr'] . $s2, $s);
$s = str_replace('[observer.webname]', substr($observer['xchan_addr'], 0, strpos($observer['xchan_addr'], '@')), $s);
$s = str_replace('[observer.photo]', '', $s);
}
$s = str_replace('[observer.baseurl]', $obsBaseURL, $s);
$s = str_replace('[observer.url]', $observer['xchan_url'], $s);
$s = str_replace('[observer.name]', $s1 . $observer['xchan_name'] . $s2, $s);
$s = str_replace('[observer.address]', $s1 . $observer['xchan_addr'] . $s2, $s);
$s = str_replace('[observer.webname]', substr($observer['xchan_addr'], 0, strpos($observer['xchan_addr'], '@')), $s);
$s = str_replace('[observer.photo]', '', $s);
}
else {
$s = str_replace('[observer.baseurl]', '', $s);
$s = str_replace('[observer.url]', '', $s);
@@ -637,62 +643,63 @@ class NativeWikiPage {
return $s;
}
static public function get_file_ext($arr) {
if($arr['mimetype'] === 'text/bbcode')
if ($arr['mimetype'] === 'text/bbcode')
return '.bb';
elseif($arr['mimetype'] === 'text/markdown')
elseif ($arr['mimetype'] === 'text/markdown')
return '.md';
elseif($arr['mimetype'] === 'text/plain')
elseif ($arr['mimetype'] === 'text/plain')
return '.txt';
}
// This function is derived from
// This function is derived from
// http://stackoverflow.com/questions/32068537/generate-table-of-contents-from-markdown-in-php
static public function toc($content) {
// ensure using only "\n" as line-break
$source = str_replace(["\r\n", "\r"], "\n", $content);
// look for markdown TOC items
preg_match_all(
'/^(?:=|-|#).*$/m',
$source,
$matches,
PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE
);
// preprocess: iterate matched lines to create an array of items
// where each item is an array(level, text)
$file_size = strlen($source);
foreach ($matches[0] as $item) {
$found_mark = substr($item[0], 0, 1);
if ($found_mark == '#') {
// text is the found item
$item_text = $item[0];
$item_level = strrpos($item_text, '#') + 1;
$item_text = substr($item_text, $item_level);
} else {
// text is the previous line (empty if <hr>)
$item_offset = $item[1];
$prev_line_offset = strrpos($source, "\n", -($file_size - $item_offset + 2));
$item_text =
substr($source, $prev_line_offset, $item_offset - $prev_line_offset - 1);
$item_text = trim($item_text);
$item_level = $found_mark == '=' ? 1 : 2;
// ensure using only "\n" as line-break
$source = str_replace(["\r\n", "\r"], "\n", $content);
// look for markdown TOC items
preg_match_all(
'/^(?:=|-|#).*$/m',
$source,
$matches,
PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE
);
// preprocess: iterate matched lines to create an array of items
// where each item is an array(level, text)
$file_size = strlen($source);
foreach ($matches[0] as $item) {
$found_mark = substr($item[0], 0, 1);
if ($found_mark == '#') {
// text is the found item
$item_text = $item[0];
$item_level = strrpos($item_text, '#') + 1;
$item_text = substr($item_text, $item_level);
}
else {
// text is the previous line (empty if <hr>)
$item_offset = $item[1];
$prev_line_offset = strrpos($source, "\n", -($file_size - $item_offset + 2));
$item_text =
substr($source, $prev_line_offset, $item_offset - $prev_line_offset - 1);
$item_text = trim($item_text);
$item_level = $found_mark == '=' ? 1 : 2;
}
if (!trim($item_text) or strpos($item_text, '|') !== FALSE) {
// item is an horizontal separator or a table header, don't mind
continue;
}
$raw_toc[] = ['level' => $item_level, 'text' => trim($item_text)];
}
if (!trim($item_text) OR strpos($item_text, '|') !== FALSE) {
// item is an horizontal separator or a table header, don't mind
continue;
}
$raw_toc[] = ['level' => $item_level, 'text' => trim($item_text)];
}
$o = '';
foreach($raw_toc as $t) {
foreach ($raw_toc as $t) {
$level = intval($t['level']);
$text = $t['text'];
$text = $t['text'];
switch ($level) {
case 1:
$li = '* ';
@@ -712,7 +719,7 @@ class NativeWikiPage {
}
$o .= $li . $text . "\n";
}
return $o;
return $o;
}
}

View File

@@ -2,6 +2,9 @@
namespace Zotlabs\Lib;
use Zotlabs\Zot6\Receiver;
use Zotlabs\Zot6\Zot6Handler;
class Queue {
static function update($id, $add_priority = 0) {
@@ -28,19 +31,19 @@ class Queue {
$might_be_down = ((datetime_convert('UTC','UTC',$y[0]['earliest']) < datetime_convert('UTC','UTC','now - 2 days')) ? true : false);
// Set all other records for this destination way into the future.
// Set all other records for this destination way into the future.
// The queue delivers by destination. We'll keep one queue item for
// this destination (this one) with a shorter delivery. If we succeed
// once, we'll try to deliver everything for that destination.
// The delivery will be set to at most once per hour, and if the
// The delivery will be set to at most once per hour, and if the
// queue item is less than 12 hours old, we'll schedule for fifteen
// minutes.
// minutes.
q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_posturl = '%s'",
dbesc(datetime_convert('UTC','UTC','now + 5 days')),
dbesc($x[0]['outq_posturl'])
);
$since = datetime_convert('UTC','UTC',$x[0]['outq_created']);
if(($might_be_down) || ($since < datetime_convert('UTC','UTC','now - 12 hour'))) {
@@ -50,9 +53,9 @@ class Queue {
$next = datetime_convert('UTC','UTC','now + ' . intval($add_priority) . ' minutes');
}
q("UPDATE outq SET outq_updated = '%s',
outq_priority = outq_priority + %d,
outq_scheduled = '%s'
q("UPDATE outq SET outq_updated = '%s',
outq_priority = outq_priority + %d,
outq_scheduled = '%s'
WHERE outq_hash = '%s'",
dbesc(datetime_convert()),
@@ -66,7 +69,7 @@ class Queue {
static function remove($id,$channel_id = 0) {
logger('queue: remove queue item ' . $id,LOGGER_DEBUG);
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
q("DELETE FROM outq WHERE outq_hash = '%s' $sql_extra",
dbesc($id)
);
@@ -75,7 +78,7 @@ class Queue {
static function remove_by_posturl($posturl) {
logger('queue: remove queue posturl ' . $posturl,LOGGER_DEBUG);
q("DELETE FROM outq WHERE outq_posturl = '%s' ",
dbesc($posturl)
);
@@ -88,7 +91,7 @@ class Queue {
$sql_extra = (($channel['channel_id']) ? " and outq_channel = " . intval($channel['channel_id']) . " " : '');
// Set the next scheduled run date so far in the future that it will be expired
// long before it ever makes it back into the delivery chain.
// long before it ever makes it back into the delivery chain.
q("update outq set outq_delivered = 1, outq_updated = '%s', outq_scheduled = '%s' where outq_hash = '%s' $sql_extra ",
dbesc(datetime_convert()),
@@ -108,7 +111,7 @@ class Queue {
}
$x = q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_priority,
outq_created, outq_updated, outq_scheduled, outq_notify, outq_msg )
outq_created, outq_updated, outq_scheduled, outq_notify, outq_msg )
values ( '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s' )",
dbesc($arr['hash']),
intval($arr['account_id']),
@@ -133,7 +136,7 @@ class Queue {
$base = null;
$h = parse_url($outq['outq_posturl']);
if($h !== false)
if($h !== false)
$base = $h['scheme'] . '://' . $h['host'] . (isset($h['port']) ? ':' . $h['port'] : '');
if(($base) && ($base !== z_root()) && ($immediate)) {
@@ -147,7 +150,7 @@ class Queue {
return;
}
if($y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) {
self::update($outq['outq_hash'],10);
self::update($outq['outq_hash'], 10);
logger('immediate delivery deferred for site ' . $base);
return;
}
@@ -158,12 +161,12 @@ class Queue {
// your site has existed. Since we don't know for sure what these sites are,
// call them unknown
site_store_lowlevel(
site_store_lowlevel(
[
'site_url' => $base,
'site_update' => datetime_convert(),
'site_dead' => 0,
'site_type' => intval(($outq['outq_driver'] === 'post') ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN),
'site_type' => SITE_TYPE_UNKNOWN,
'site_crypto' => ''
]
);
@@ -171,65 +174,17 @@ class Queue {
}
$arr = array('outq' => $outq, 'base' => $base, 'handled' => false, 'immediate' => $immediate);
call_hooks('queue_deliver',$arr);
call_hooks('queue_deliver', $arr);
if($arr['handled'])
return;
// "post" queue driver - used for diaspora and friendica-over-diaspora communications.
if($outq['outq_driver'] === 'post') {
$result = z_post_url($outq['outq_posturl'],$outq['outq_msg']);
if($result['success'] && $result['return_code'] < 300) {
logger('deliver: queue post success to ' . $outq['outq_posturl'], LOGGER_DEBUG);
if($base) {
q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ",
dbesc(datetime_convert()),
dbesc($base)
);
}
q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
dbesc('accepted for delivery'),
dbesc(datetime_convert()),
dbesc($outq['outq_hash'])
);
self::remove($outq['outq_hash']);
// server is responding - see if anything else is going to this destination and is piled up
// and try to send some more. We're relying on the fact that do_delivery() results in an
// immediate delivery otherwise we could get into a queue loop.
if(! $immediate) {
$x = q("select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
dbesc($outq['outq_posturl'])
);
$piled_up = array();
if($x) {
foreach($x as $xx) {
$piled_up[] = $xx['outq_hash'];
}
}
if($piled_up) {
// call do_delivery() with the force flag
do_delivery($piled_up, true);
}
}
}
else {
logger('deliver: queue post returned ' . $result['return_code']
. ' from ' . $outq['outq_posturl'],LOGGER_DEBUG);
self::update($outq['outq_hash'],10);
}
return;
}
// normal zot delivery
logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG);
if($outq['outq_posturl'] === z_root() . '/zot') {
// local delivery
$zot = new \Zotlabs\Zot6\Receiver(new \Zotlabs\Zot6\Zot6Handler(),$outq['outq_notify']);
$zot = new Receiver(new Zot6Handler(), $outq['outq_notify']);
$result = $zot->run();
logger('returned_json: ' . json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
logger('deliver: local zot delivery succeeded to ' . $outq['outq_posturl']);
@@ -240,13 +195,14 @@ class Queue {
$channel = null;
if($outq['outq_channel']) {
$channel = channelx_by_n($outq['outq_channel']);
$channel = channelx_by_n($outq['outq_channel'], true);
}
$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' and hubloc_sitekey != '' 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_network = 'zot6' ORDER BY hubloc_id DESC LIMIT 1",
dbesc($base)
);
if($h) {
@@ -256,7 +212,7 @@ class Queue {
$msg = $outq['outq_notify'];
$result = Libzot::zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
$result = Libzot::zot($outq['outq_posturl'], $msg, $channel, $host_crypto);
if($result['success']) {
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
@@ -265,7 +221,7 @@ class Queue {
else {
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA);
self::update($outq['outq_hash'],10);
self::update($outq['outq_hash'], 10);
}
}
return;

View File

@@ -8,13 +8,13 @@ class Share {
public function __construct($post_id) {
if(! $post_id)
return;
if(! (local_channel() || remote_channel()))
return;
$r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1",
intval($post_id)
);
@@ -23,26 +23,26 @@ class Share {
if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss'))
return;
$sql_extra = item_permissions_sql($r[0]['uid']);
$r = q("select * from item where id = %d $sql_extra",
intval($post_id)
);
if(! $r)
return;
if($r[0]['mimetype'] !== 'text/bbcode')
return;
/** @FIXME eventually we want to post remotely via rpost on your home site */
// When that works remove this next bit:
if(! local_channel())
return;
xchan_query($r);
$this->item = $r[0];
return;
}
@@ -66,14 +66,14 @@ class Share {
'address' => $this->item['author']['xchan_addr'],
'network' => $this->item['author']['xchan_network'],
'link' => [
[
'rel' => 'alternate',
'type' => 'text/html',
[
'rel' => 'alternate',
'type' => 'text/html',
'href' => $this->item['author']['xchan_url']
],
[
'rel' => 'photo',
'type' => $this->item['author']['xchan_photo_mimetype'],
'rel' => 'photo',
'type' => $this->item['author']['xchan_photo_mimetype'],
'href' => $this->item['author']['xchan_photo_m']
]
]
@@ -84,14 +84,14 @@ class Share {
'address' => $this->item['owner']['xchan_addr'],
'network' => $this->item['owner']['xchan_network'],
'link' => [
[
'rel' => 'alternate',
'type' => 'text/html',
[
'rel' => 'alternate',
'type' => 'text/html',
'href' => $this->item['owner']['xchan_url']
],
[
'rel' => 'photo',
'type' => $this->item['owner']['xchan_photo_mimetype'],
'rel' => 'photo',
'type' => $this->item['owner']['xchan_photo_mimetype'],
'href' => $this->item['owner']['xchan_photo_m']
]
]
@@ -117,7 +117,7 @@ class Share {
$object = json_decode($this->item['obj'],true);
$photo_bb = $object['body'];
}
if (strpos($this->item['body'], "[/share]") !== false) {
$pos = strpos($this->item['body'], "[share");
$bb = substr($this->item['body'], $pos);
@@ -126,7 +126,7 @@ class Share {
"' profile='" . $this->item['author']['xchan_url'] .
"' avatar='" . $this->item['author']['xchan_photo_s'] .
"' link='" . $this->item['plink'] .
"' auth='" . ((in_array($this->item['author']['xchan_network'], ['zot6', 'zot'])) ? 'true' : 'false') .
"' auth='" . (($this->item['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
"' posted='" . $this->item['created'] .
"' message_id='" . $this->item['mid'] .
"']";

View File

@@ -299,7 +299,7 @@ class ThreadItem {
);
*/
$settings = t('Conversation Tools');
$settings = t('Conversation Features');
}
$has_bookmarks = false;
@@ -367,7 +367,7 @@ class ThreadItem {
call_hooks('dropdown_extras',$dropdown_extras_arr);
$dropdown_extras = $dropdown_extras_arr['dropdown_extras'];
$midb64 = 'b64.' . base64url_encode($item['mid']);
$midb64 = gen_link_id($item['mid']);
$mids = [ $midb64 ];
$response_mids = [];
foreach($response_verbs as $v) {
@@ -503,7 +503,7 @@ class ThreadItem {
'wait' => t('Please wait'),
'thread_level' => $thread_level,
'settings' => $settings,
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? 'b64.' . base64url_encode($item['thr_parent']) : '')
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? gen_link_id($item['thr_parent']) : '')
);
$arr = array('item' => $item, 'output' => $tmp_item);
@@ -842,7 +842,7 @@ class ThreadItem {
'$cipher' => $conv->get_cipher(),
'$sourceapp' => \App::$sourcename,
'$observer' => get_observer_hash(),
'$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false),
'$anoncomments' => ((in_array($conv->get_mode(), ['channel', 'display', 'cards', 'articles']) && 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)') ]

View File

@@ -77,7 +77,7 @@ class ThreadStream {
$this->reload = $_SESSION['return_url'];
break;
case 'display':
// in this mode we set profile_owner after initialisation (from conversation()) and then
// in this mode we set profile_owner after initialisation (from conversation()) and then
// pull some trickery which allows us to re-invoke this function afterward
// it's an ugly hack so @FIXME
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
@@ -170,14 +170,14 @@ class ThreadStream {
* Only add things that will be displayed
*/
if(($item->get_data_value('id') != $item->get_data_value('parent')) && (activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE))) {
return false;
}
$item->set_commentable(false);
$ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
if(! comments_are_now_closed($item->get_data())) {
if(($item->get_data_value('author_xchan') === $ob_hash) || ($item->get_data_value('owner_xchan') === $ob_hash))
$item->set_commentable(true);
@@ -194,7 +194,7 @@ class ThreadStream {
}
if($this->mode === 'pubstream' && (! local_channel())) {
$item->set_commentable(false);
}
}
$item->set_conversation($this);

View File

@@ -222,6 +222,7 @@ class Acl extends \Zotlabs\Web\Controller {
WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" ,
intval(local_channel())
);
if($r2)
$r = array_merge($r2,$r);
@@ -282,13 +283,12 @@ class Acl extends \Zotlabs\Web\Controller {
}
}
elseif($type == 'm') {
$r = array();
$z = q("SELECT xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
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')
and not xchan_network IN ('rss', 'anon', 'unknown')
$sql_extra3
ORDER BY xchan_name ASC ",
intval(local_channel())
@@ -371,7 +371,7 @@ class Acl extends \Zotlabs\Web\Controller {
);
}
if($type !== 'f') {
if (! array_key_exists($x[$lkey], $contacts) || ($contacts[$x[$lkey]]['net'] !== 'zot6' && ($g['net'] == 'zot6' || $g['net'] == 'zot'))) {
if (! array_key_exists($x[$lkey], $contacts) || ($contacts[$x[$lkey]]['net'] !== 'zot6' && $g['net'] == 'zot6')) {
$contacts[$x[$lkey]] = array(
"type" => "c",
"photo" => $g['micro'],
@@ -438,7 +438,6 @@ class Acl extends \Zotlabs\Web\Controller {
}
if(! $url) {
require_once("include/dir_fns.php");
$directory = Libzotdir::find_upstream_directory($dirmode);
$url = $directory['url'] . '/dirsearch';
}

View File

@@ -8,7 +8,6 @@
namespace Zotlabs\Module;
require_once('include/queue_fn.php');
require_once('include/account.php');
/**

View File

@@ -2,35 +2,35 @@
namespace Zotlabs\Module\Admin;
use Zotlabs\Lib\Queue as LibQueue;
class Queue {
function get() {
$o = '';
$expert = ((array_key_exists('expert',$_REQUEST)) ? intval($_REQUEST['expert']) : 0);
if($_REQUEST['drophub']) {
hubloc_mark_as_down($_REQUEST['drophub']);
remove_queue_by_posturl($_REQUEST['drophub']);
LibQueue::remove_by_posturl($_REQUEST['drophub']);
}
if($_REQUEST['emptyhub']) {
remove_queue_by_posturl($_REQUEST['emptyhub']);
LibQueue::remove_by_posturl($_REQUEST['emptyhub']);
}
$r = q("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq
$r = q("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq
where outq_delivered = 0 group by outq_posturl order by total desc");
for($x = 0; $x < count($r); $x ++) {
$r[$x]['eurl'] = urlencode($r[$x]['outq_posturl']);
$r[$x]['connected'] = datetime_convert('UTC',date_default_timezone_get(),$r[$x]['connected'],'Y-m-d');
}
$o = replace_macros(get_markup_template('admin_queue.tpl'), array(
'$banner' => t('Queue Statistics'),
'$numentries' => t('Total Entries'),
@@ -43,11 +43,11 @@ class Queue {
'$entries' => $r,
'$expert' => $expert
));
return $o;
}
}
}

View File

@@ -480,12 +480,12 @@ class Site {
'$invitation_only' => [
'invitation_only',
t("Require invite code"),
$invitation_only
get_config('system', 'invitation_only', 0)
],
'$invitation_also' => [
'invitation_also',
t("Allow invite code"),
$invitation_also
get_config('system', 'invitation_also', 0)
],
'$verify_email' => [
'verify_email',

View File

@@ -44,17 +44,14 @@ class Affinity extends \Zotlabs\Web\Controller {
if(! local_channel())
return;
$desc = t('This app presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship (affinity) with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.');
if(! Apps::system_app_installed(local_channel(),'Affinity Tool')) {
if(! Apps::system_app_installed(local_channel(), 'Affinity Tool')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Affinity Tool App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= $desc;
return $o;
$papp = Apps::get_papp('Affinity Tool');
return Apps::app_render($papp, 'module');
}
$text = t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.');
$text = t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.');
$content = '<div class="section-content-info-wrapper">' . $text . '</div>';

103
Zotlabs/Module/Album.php Normal file
View File

@@ -0,0 +1,103 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Config;
use Zotlabs\Web\HTTPSig;
require_once('include/security.php');
require_once('include/attach.php');
require_once('include/photo/photo_driver.php');
require_once('include/photos.php');
class Album extends Controller {
function init() {
if (ActivityStreams::is_as_request()) {
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
$portable_id = $sigdata['portable_id'];
if (!check_channelallowed($portable_id)) {
http_status_exit(403, 'Permission denied');
}
if (!check_siteallowed($sigdata['signer'])) {
http_status_exit(403, 'Permission denied');
}
observer_auth($portable_id);
}
elseif (Config::get('system', 'require_authenticated_fetch', false)) {
http_status_exit(403, 'Permission denied');
}
$observer_xchan = get_observer_hash();
$allowed = false;
$bear = Activity::token_from_request();
if ($bear) {
logger('bear: ' . $bear, LOGGER_DEBUG);
}
$channel = null;
if (argc() > 1) {
$channel = channelx_by_nick(argv(1));
}
if (!$channel) {
http_status_exit(404, 'Not found.');
}
$sql_extra = permissions_sql($channel['channel_id'], $observer_xchan);
if (argc() > 2) {
$folder = argv(2);
$r = q("select * from attach where is_dir = 1 and hash = '%s' and uid = %d $sql_extra limit 1",
dbesc($folder),
intval($channel['channel_id'])
);
$allowed = (($r) ? attach_can_view($channel['channel_id'], $observer_xchan, $r[0]['hash'] /*,$bear */) : false);
}
else {
$folder = EMPTY_STR;
$allowed = perm_is_allowed($channel['channel_id'], $observer_xchan, 'view_storage');
}
if (!$allowed) {
http_status_exit(403, 'Permission denied.');
}
$x = q("select * from attach where folder = '%s' and uid = %d $sql_extra",
dbesc($folder),
intval($channel['channel_id'])
);
$contents = [];
if ($x) {
foreach ($x as $xv) {
if (intval($xv['is_dir'])) {
continue;
}
if (!attach_can_view($channel['channel_id'], $observer_xchan, $xv['hash'] /*,$bear*/)) {
continue;
}
if (intval($xv['is_photo'])) {
$contents[] = z_root() . '/photo/' . $xv['hash'];
}
}
}
$obj = Activity::encode_simple_collection($contents, App::$query_string, 'OrderedCollection', count($contents));
as_return_and_die($obj, $channel);
}
}
}

View File

@@ -1,18 +1,18 @@
<?php /** @file */
namespace Zotlabs\Module;
namespace Zotlabs\Module;
//require_once('include/apps.php');
use \Zotlabs\Lib as Zlib;
use App;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libsync;
class Appman extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
if($_POST['url']) {
$arr = array(
'uid' => intval($_REQUEST['uid']),
@@ -32,32 +32,70 @@ class Appman extends \Zotlabs\Web\Controller {
'sig' => escape_tags($_REQUEST['sig']),
'categories' => escape_tags($_REQUEST['categories'])
);
$_REQUEST['appid'] = Zlib\Apps::app_install(local_channel(),$arr);
if(Zlib\Apps::app_installed(local_channel(),$arr))
$_REQUEST['appid'] = Apps::app_install(local_channel(),$arr);
if(Apps::app_installed(local_channel(),$arr))
info( t('App installed.') . EOL);
goaway(z_root() . '/apps');
return; //not reached
}
$papp = Zlib\Apps::app_decode($_POST['papp']);
$papp = Apps::app_decode($_POST['papp']);
if(! is_array($papp)) {
notice( t('Malformed app.') . EOL);
return;
}
if($_POST['install']) {
Zlib\Apps::app_install(local_channel(),$papp);
if(Zlib\Apps::app_installed(local_channel(),$papp))
Apps::app_install(local_channel(),$papp);
if(Apps::app_installed(local_channel(),$papp))
info( t('App installed.') . EOL);
$sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
intval(local_channel()),
dbesc($papp['guid'])
);
if (!$sync) {
return;
}
if (intval($sync[0]['app_system'])) {
Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
}
else {
Libsync::build_sync_packet($uid, ['app' => $sync]);
}
}
if($_POST['delete']) {
Zlib\Apps::app_destroy(local_channel(),$papp);
// Fetch the app for sync before it is deleted (if it is deletable))
$sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
intval(local_channel()),
dbesc($papp['guid'])
);
if (!$sync) {
return;
}
Apps::app_destroy(local_channel(), $papp);
// Now flag it deleted
$sync[0]['app_deleted'] = 1;
if (intval($sync[0]['app_system'])) {
Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
}
else {
Libsync::build_sync_packet($uid, ['app' => $sync]);
}
}
if($_POST['edit']) {
@@ -65,37 +103,65 @@ class Appman extends \Zotlabs\Web\Controller {
}
if($_POST['feature']) {
Zlib\Apps::app_feature(local_channel(), $papp, $_POST['feature']);
Apps::app_feature(local_channel(), $papp, $_POST['feature']);
$sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
intval(local_channel()),
dbesc($papp['guid'])
);
if (intval($sync[0]['app_system'])) {
Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
}
else {
Libsync::build_sync_packet($uid, ['app' => $sync]);
}
}
if($_POST['pin']) {
Zlib\Apps::app_feature(local_channel(), $papp, $_POST['pin']);
Apps::app_feature(local_channel(), $papp, $_POST['pin']);
$sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
intval(local_channel()),
dbesc($papp['guid'])
);
if (intval($sync[0]['app_system'])) {
Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
}
else {
Libsync::build_sync_packet($uid, ['app' => $sync]);
}
}
if($_SESSION['return_url'])
if($_POST['aj']) {
killme();
}
if($_SESSION['return_url'])
goaway(z_root() . '/' . $_SESSION['return_url']);
goaway(z_root() . '/apps');
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$channel = \App::get_channel();
$channel = App::get_channel();
if(argc() > 3) {
if(argv(2) === 'moveup') {
Zlib\Apps::moveup(local_channel(),argv(1),argv(3));
Apps::moveup(local_channel(),argv(1),argv(3));
}
if(argv(2) === 'movedown') {
Zlib\Apps::movedown(local_channel(),argv(1),argv(3));
Apps::movedown(local_channel(),argv(1),argv(3));
}
goaway(z_root() . '/apporder');
}
@@ -129,12 +195,12 @@ class Appman extends \Zotlabs\Web\Controller {
}
}
$embed = array('embed', t('Embed code'), Zlib\Apps::app_encode($app,true),'', 'onclick="this.select();"');
$embed = array('embed', t('Embed code'), Apps::app_encode($app,true),'', 'onclick="this.select();"');
}
return replace_macros(get_markup_template('app_create.tpl'), array(
'$banner' => (($app) ? t('Edit App') : t('Create App')),
'$app' => $app,
'$guid' => (($app) ? $app['app_id'] : ''),
@@ -154,7 +220,7 @@ class Appman extends \Zotlabs\Web\Controller {
'$embed' => $embed,
'$submit' => t('Submit')
));
}
}

View File

@@ -9,7 +9,7 @@ class Apps extends \Zotlabs\Web\Controller {
function get() {
nav_set_selected('Apps');
if(argc() == 2 && argv(1) == 'edit')
$mode = 'edit';
else
@@ -18,9 +18,9 @@ class Apps extends \Zotlabs\Web\Controller {
$available = ((argc() == 2 && argv(1) === 'available') ? true : false);
$_SESSION['return_url'] = \App::$query_string;
$apps = array();
if(local_channel()) {
Zlib\Apps::import_system_apps();
$syslist = array();
@@ -37,9 +37,9 @@ class Apps extends \Zotlabs\Web\Controller {
$syslist = Zlib\Apps::get_system_apps(true);
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
// logger('apps: ' . print_r($syslist,true));
foreach($syslist as $app) {
$apps[] = Zlib\Apps::app_render($app,(($available) ? 'install' : $mode));
}
@@ -53,7 +53,7 @@ class Apps extends \Zotlabs\Web\Controller {
'$manage' => (($available) ? '' : t('Manage Apps')),
'$create' => (($mode == 'edit') ? t('Create Custom App') : '')
));
}
}

View File

@@ -50,7 +50,7 @@ class Apschema extends \Zotlabs\Web\Controller {
'guid' => 'diaspora:guid',
'Hashtag' => 'as:Hashtag'
]
];

View File

@@ -85,7 +85,6 @@ class Article_edit extends \Zotlabs\Web\Controller {
$mimetype = $itm[0]['mimetype'];
$summary = (($itm[0]['summary']) ? '[summary]' . $itm[0]['summary'] . '[/summary]' . "\r\n" : '');
$content = $itm[0]['body'];
$rp = 'articles/' . $channel['channel_address'];
@@ -109,7 +108,7 @@ class Article_edit extends \Zotlabs\Web\Controller {
'ptyp' => $itm[0]['type'],
'mimeselect' => false,
'mimetype' => $itm[0]['mimetype'],
'body' => $summary . undo_post_tagging($content),
'body' => undo_post_tagging($content),
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),

View File

@@ -48,10 +48,8 @@ class Articles extends Controller {
if(! Apps::system_app_installed(App::$profile_uid, 'Articles')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Articles App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Create interactive articles');
return $o;
$papp = Apps::get_papp('Articles');
return Apps::app_render($papp, 'module');
}
nav_set_selected('Articles');

View File

@@ -1,41 +1,38 @@
<?php
namespace Zotlabs\Module;
require_once('include/zot.php');
class Authtest extends \Zotlabs\Web\Controller {
function get() {
$auth_success = false;
$o .= '<h3>Magic-Auth Diagnostic</h3>';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return $o;
}
$o .= '<form action="authtest" method="get">';
$o .= 'Target URL: <input type="text" style="width: 250px;" name="dest" value="' . $_GET['dest'] .'" />';
$o .= '<input type="submit" name="submit" value="Submit" /></form>';
$o .= '<input type="submit" name="submit" value="Submit" /></form>';
$o .= '<br /><br />';
if(x($_GET,'dest')) {
if(strpos($_GET['dest'],'@')) {
$_GET['dest'] = $_REQUEST['dest'] = 'https://' . substr($_GET['dest'],strpos($_GET['dest'],'@')+1) . '/channel/' . substr($_GET['dest'],0,strpos($_GET['dest'],'@'));
}
$_REQUEST['test'] = 1;
$mod = new Magic();
$x = $mod->init($a);
$o .= 'Local Setup returns: ' . print_r($x,true);
if($x['url']) {
$z = z_fetch_url($x['url'] . '&test=1');
if($z['success']) {
@@ -50,12 +47,12 @@ class Authtest extends \Zotlabs\Web\Controller {
$o .= 'fetch url failure.' . print_r($z,true);
}
}
if(! $auth_success)
$o .= 'Authentication Failed!' . EOL;
}
return str_replace("\n",'<br />',$o);
}
}

View File

@@ -18,31 +18,31 @@ class Bookmarks extends \Zotlabs\Web\Controller {
$item_id = (isset($_REQUEST['item']) ? $_REQUEST['item'] : false);
$burl = (isset($_REQUEST['burl']) ? trim($_REQUEST['burl']) : '');
if(! $item_id)
return;
$u = \App::get_channel();
$item_normal = item_normal();
$i = q("select * from item where id = %d and uid = %d $item_normal limit 1",
intval($item_id),
intval(local_channel())
);
if(! $i)
return;
$i = fetch_post_tags($i);
$item = $i[0];
$terms = (x($item, 'term') ? get_terms_oftype($item['term'],TERM_BOOKMARK) : false);
if($terms) {
require_once('include/bookmarks.php');
$s = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['author_xchan'])
);
@@ -58,13 +58,13 @@ class Bookmarks extends \Zotlabs\Web\Controller {
}
else
bookmark_add($u,$s[0],$t,$item['item_private']);
info( t('Bookmark added') . EOL);
}
}
killme();
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
@@ -74,49 +74,47 @@ class Bookmarks extends \Zotlabs\Web\Controller {
if(! Apps::system_app_installed(local_channel(), 'Bookmarks')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Bookmarks App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Bookmark links from posts and manage them');
return $o;
$papp = Apps::get_papp('Bookmarks');
return Apps::app_render($papp, 'module');
}
require_once('include/menu.php');
require_once('include/conversation.php');
$channel = \App::get_channel();
$o = '';
$o .= '<div class="generic-content-wrapper-styled">';
$o .= '<h3>' . t('My Bookmarks') . '</h3>';
$o .= '<h3>' . t('Bookmarks') . '</h3>';
$x = menu_list(local_channel(),'',MENU_BOOKMARK);
if($x) {
foreach($x as $xx) {
$y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash());
$o .= menu_render($y,'',true);
}
}
$o .= '<h3>' . t('My Connections Bookmarks') . '</h3>';
$x = menu_list(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
if($x) {
foreach($x as $xx) {
$y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash());
$o .= menu_render($y,'',true);
}
}
$o .= '</div>';
return $o;
}
}

View File

@@ -47,10 +47,8 @@ class Cards extends Controller {
if(! Apps::system_app_installed(App::$profile_uid, 'Cards')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Cards App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Create personal planning cards');
return $o;
$papp = Apps::get_papp('Cards');
return Apps::app_render($papp, 'module');
}
nav_set_selected('Cards');

View File

@@ -873,10 +873,8 @@ class Cdav extends Controller {
if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('CardDAV App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('CalDAV capable addressbook');
return $o;
$papp = Apps::get_papp('CardDAV');
return Apps::app_render($papp, 'module');
}
App::$profile_uid = local_channel();
@@ -1059,6 +1057,7 @@ class Cdav extends Controller {
'$cancel' => t('Cancel'),
'$create' => t('Create'),
'$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.'),
'$disabled_warning' => t('Could not fetch calendar resource. The selected calendar might be disabled.'),
'$channel_hash' => $channel['channel_hash'],
'$acl' => $acl,

View File

@@ -46,14 +46,15 @@ class Channel extends Controller {
}
$profile = 0;
$channel = App::get_channel();
if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$channel = App::get_channel();
$which = $channel['channel_address'];
$profile = argv(1);
}
$channel = channelx_by_nick($which);
$channel = channelx_by_nick($which, true);
if (!$channel) {
http_status_exit(404, 'Not found');
}
@@ -66,7 +67,8 @@ class Channel extends Controller {
if ($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
$data = json_encode(Libzot::zotinfo(['address' => $channel['channel_address'], 'target_url' => $sigdata['signer']]));
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
dbesc($sigdata['signer'])
);
@@ -83,24 +85,27 @@ class Channel extends Controller {
'Digest' => HTTPSig::generate_digest_header($data),
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
];
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
HTTPSig::set_headers($h);
echo $data;
killme();
}
if ($channel['channel_removed']) {
http_status_exit(410, 'Gone');
}
if (ActivityStreams::is_as_request($channel)) {
// Somebody may attempt an ActivityStreams fetch on one of our message permalinks
// Make it do the right thing.
$mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
if ($mid && strpos($mid, 'b64.') === 0) {
$decoded = @base64url_decode(substr($mid, 4));
if ($decoded) {
$mid = $decoded;
}
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
if ($mid === false) {
http_status_exit(404, 'Not found');
}
if ($mid) {
$obj = null;
if (strpos($mid, z_root() . '/item/') === 0) {
@@ -145,15 +150,19 @@ class Channel extends Controller {
profile_load($which, $profile);
// Add Opengraph markup
$mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
if (strpos($mid, 'b64.') === 0)
$mid = @base64url_decode(substr($mid, 4));
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
if ($mid)
if ($mid === false) {
notice(t('Malformed message id.') . EOL);
return;
}
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((isset($r) && count($r) ? $r[0] : []), $channel);
}
@@ -164,12 +173,11 @@ class Channel extends Controller {
$category = $datequery = $datequery2 = '';
$mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
if (strpos($mid, 'b64.') === 0)
$decoded = @base64url_decode(substr($mid, 4));
if (isset($decoded))
$mid = $decoded;
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
if ($mid === false) {
notice(t('Malformed message id.') . EOL);
return;
}
$datequery = ((x($_GET, 'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET, 'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
@@ -213,7 +221,7 @@ class Channel extends Controller {
if (!$update) {
nav_set_selected('Channel Home');
nav_set_selected('Channel');
// search terms header
if ($search) {
@@ -420,8 +428,8 @@ class Channel extends Controller {
if ((!$update) && (!$load)) {
if (isset($decoded))
$mid = 'b64.' . base64url_encode($mid);
//if we got a decoded hash we must encode it again before handing to javascript
$mid = gen_link_id($mid);
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.

View File

@@ -10,49 +10,49 @@ use Zotlabs\Lib\Zotfinger;
class Chanview extends \Zotlabs\Web\Controller {
function get() {
$observer = App::get_observer();
$xchan = null;
$r = null;
if($_REQUEST['hash']) {
$r = q("select * from xchan where xchan_hash = '%s'",
$r = q("select * from xchan where xchan_hash = '%s' and xchan_deleted = 0",
dbesc($_REQUEST['hash'])
);
}
if($_REQUEST['address']) {
$r = q("select * from xchan where xchan_addr = '%s'",
$r = q("select * from xchan where xchan_addr = '%s' and xchan_deleted = 0",
dbesc(punify($_REQUEST['address']))
);
}
elseif(local_channel() && intval($_REQUEST['cid'])) {
$r = q("SELECT abook.*, xchan.*
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d",
WHERE abook_channel = %d and abook_id = %d and xchan_deleted = 0",
intval(local_channel()),
intval($_REQUEST['cid'])
);
}
}
elseif($_REQUEST['url']) {
// if somebody re-installed they will have more than one xchan, use the most recent name date as this is
// the most useful consistently ascending table item we have.
$r = q("select * from xchan where xchan_url = '%s' order by xchan_name_date desc",
// the most useful consistently ascending table item we have.
$r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0 order by xchan_name_date desc",
dbesc($_REQUEST['url'])
);
}
if($r) {
App::$poi = Libzot::zot_record_preferred($r, 'xchan_network');
}
// Here, let's see if we have an xchan. If we don't, how we proceed is determined by what
// info we do have. If it's a URL, we can offer to visit it directly. If it's a webbie or
// address, we can and should try to import it. If it's just a hash, we can't continue, but we
// info we do have. If it's a URL, we can offer to visit it directly. If it's a webbie or
// address, we can and should try to import it. If it's just a hash, we can't continue, but we
// probably wouldn't have a hash if we don't already have an xchan for this channel.
if(! App::$poi) {
logger('mod_chanview: fallback');
@@ -71,7 +71,7 @@ class Chanview extends \Zotlabs\Web\Controller {
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $_REQUEST['url'] && intval($zf['signature']['header_valid'])) {
Libzot::import_xchan($zf['data']);
$r = q("select * from xchan where xchan_url = '%s'",
$r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0",
dbesc($_REQUEST['url'])
);
if($r) {
@@ -80,7 +80,7 @@ class Chanview extends \Zotlabs\Web\Controller {
}
if(! $r) {
if(discover_by_webbie($_REQUEST['url'])) {
$r = q("select * from xchan where xchan_url = '%s'",
$r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0",
dbesc($_REQUEST['url'])
);
if($r) {
@@ -90,7 +90,7 @@ class Chanview extends \Zotlabs\Web\Controller {
}
}
}
if(! App::$poi) {
notice( t('Channel not found.') . EOL);
return;
@@ -98,9 +98,9 @@ class Chanview extends \Zotlabs\Web\Controller {
$is_zot = false;
$connected = false;
$url = App::$poi['xchan_url'];
if(in_array(App::$poi['xchan_network'], ['zot', 'zot6'])) {
if(App::$poi['xchan_network'] === 'zot6') {
$is_zot = true;
}
if(local_channel()) {
@@ -111,29 +111,29 @@ class Chanview extends \Zotlabs\Web\Controller {
if($c)
$connected = true;
}
// We will load the chanview template if it's a foreign network,
// We will load the chanview template if it's a foreign network,
// just so that we can provide a connect button along with a profile
// photo. Chances are we can't load the remote profile into an iframe
// because of cross-domain security headers. So provide a link to
// the remote profile.
// the remote profile.
// If we are already connected, just go to the profile.
// Zot channels will usually have a connect link.
if($is_zot || $connected) {
if($is_zot && $observer) {
$url = zid($url);
}
goaway($url);
}
else {
else {
$o = replace_macros(get_markup_template('chanview.tpl'),array(
'$url' => $url,
'$full' => t('toggle full screen mode')
));
return $o;
}
}
}

View File

@@ -14,7 +14,7 @@ require_once('include/bookmarks.php');
class Chat extends Controller {
function init() {
$which = null;
if(argc() > 1)
$which = argv(1);
@@ -29,79 +29,77 @@ class Chat extends Controller {
notice( t('You must be logged in to see this page.') . EOL );
return;
}
$profile = 0;
$channel = App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
$profile = argv(1);
}
// Run profile_load() here to make sure the theme is set before
// we start loading content
profile_load($which,$profile);
}
function post() {
if($_POST['room_name'])
$room = strip_tags(trim($_POST['room_name']));
$room = strip_tags(trim($_POST['room_name']));
if((! $room) || (! local_channel()))
return;
$channel = App::get_channel();
if($_POST['action'] === 'drop') {
logger('delete chatroom');
Chatroom::destroy($channel,array('cr_name' => $room));
goaway(z_root() . '/chat/' . $channel['channel_address']);
}
$acl = new AccessList($channel);
$acl->set_from_array($_REQUEST);
$arr = $acl->get();
$arr['name'] = $room;
$arr['expire'] = intval($_POST['chat_expire']);
if(intval($arr['expire']) < 0)
$arr['expire'] = 0;
Chatroom::create($channel,$arr);
$x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1",
dbesc($room),
intval(local_channel())
);
Libsync::build_sync_packet(0, array('chatroom' => $x));
if($x)
goaway(z_root() . '/chat/' . $channel['channel_address'] . '/' . $x[0]['cr_id']);
// that failed. Try again perhaps?
goaway(z_root() . '/chat/' . $channel['channel_address'] . '/new');
}
function get() {
if(! Apps::system_app_installed(App::$profile_uid, 'Chatrooms')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Chatrooms App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Access Controlled Chatrooms');
return $o;
$papp = Apps::get_papp('Chatrooms');
return Apps::app_render($papp, 'module');
}
if(local_channel()) {
$channel = App::get_channel();
nav_set_selected('Chatrooms');
@@ -113,24 +111,24 @@ class Chat extends Controller {
notice( t('Permission denied.') . EOL);
return;
}
if(! perm_is_allowed(App::$profile['profile_uid'],$observer,'chat')) {
notice( t('Permission denied.') . EOL);
return;
}
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'leave')) {
Chatroom::leave($observer,argv(2),$_SERVER['REMOTE_ADDR']);
goaway(z_root() . '/channel/' . argv(1));
}
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'status')) {
$ret = array('success' => false);
$room_id = intval(argv(2));
if(! $room_id || ! $observer)
return;
$r = q("select * from chatroom where cr_id = %d limit 1",
intval($room_id)
);
@@ -139,7 +137,7 @@ class Chat extends Controller {
}
require_once('include/security.php');
$sql_extra = permissions_sql($r[0]['cr_uid']);
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
intval($room_id),
intval($r[0]['cr_uid'])
@@ -155,9 +153,9 @@ class Chat extends Controller {
$ret['chatroom'] = $r[0]['cr_name'];
$ret['inroom'] = $y[0]['total'];
}
// figure out how to present a timestamp of the last activity, since we don't know the observer's timezone.
$z = q("select created from chat where chat_room = %d order by created desc limit 1",
intval($room_id)
);
@@ -166,13 +164,13 @@ class Chat extends Controller {
}
json_return_and_die($ret);
}
if(argc() > 2 && intval(argv(2))) {
$room_id = intval(argv(2));
$bookmark_link = get_bookmark_link($ob);
$x = Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']);
if(! $x)
return;
@@ -180,26 +178,26 @@ class Chat extends Controller {
intval($room_id),
intval(App::$profile['profile_uid'])
);
if($x) {
$acl = new AccessList(false);
$acl->set($x[0]);
$private = $acl->is_private();
$room_name = $x[0]['cr_name'];
if($bookmark_link)
$bookmark_link .= '&url=' . z_root() . '/chat/' . argv(1) . '/' . argv(2) . '&title=' . urlencode($x[0]['cr_name']) . (($private) ? '&private=1' : '') . '&ischat=1';
$bookmark_link .= '&url=' . z_root() . '/chat/' . argv(1) . '/' . argv(2) . '&title=' . urlencode($x[0]['cr_name']) . (($private) ? '&private=1' : '') . '&ischat=1';
}
else {
notice( t('Room not found') . EOL);
return;
}
$cipher = get_pconfig(local_channel(),'system','default_cipher');
if(! $cipher)
$cipher = 'AES-128-CCM';
$o = replace_macros(get_markup_template('chat.tpl'),array(
'$is_owner' => ((local_channel() && local_channel() == $x[0]['cr_uid']) ? true : false),
'$room_name' => $room_name,
@@ -223,7 +221,7 @@ class Chat extends Controller {
}
require_once('include/conversation.php');
$o = '';
$acl = new AccessList($channel);
@@ -246,12 +244,12 @@ class Chat extends Controller {
'$deny_gid' => acl2json($channel_acl['deny_gid']),
'$lockstate' => $lockstate,
'$submit' => t('Submit')
));
}
$rooms = Chatroom::roomlist(App::$profile['profile_uid']);
$o .= replace_macros(get_markup_template('chatrooms.tpl'), array(
'$header' => sprintf( t('%1$s\'s Chatrooms'), App::$profile['fullname']),
'$name' => t('Name'),
@@ -259,15 +257,15 @@ class Chat extends Controller {
'$nickname' => App::$profile['channel_address'],
'$rooms' => $rooms,
'$norooms' => t('No chatrooms available'),
'$newroom' => t('Create New'),
'$newroom' => t('Add Room'),
'$is_owner' => ((local_channel() && local_channel() == App::$profile['profile_uid']) ? 1 : 0),
'$chatroom_new' => $chatroom_new,
'$expire' => t('Expiration'),
'$expire_unit' => t('min') //minutes
));
return $o;
}
}

View File

@@ -40,12 +40,12 @@ class Connedit extends Controller {
if((argc() >= 2) && intval(argv(1))) {
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
WHERE abook_channel = %d and abook_id = %d and xchan_deleted = 0 LIMIT 1",
intval(local_channel()),
intval(argv(1))
);
if($r) {
App::$poi = array_shift($r);
App::$poi = $r[0];
}
}
@@ -220,9 +220,6 @@ class Connedit extends Controller {
if($z)
$record = $z[0]['xlink_id'];
}
if($record) {
Master::Summon(array('Ratenotif','rating',$record));
}
}
if(($_REQUEST['pending']) && intval($orig_record[0]['abook_pending'])) {
@@ -426,7 +423,7 @@ class Connedit extends Controller {
$cmd = argv(2);
$orig_record = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1",
WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 and xchan_deleted = 0 LIMIT 1",
intval($contact_id),
intval(local_channel())
);
@@ -478,16 +475,11 @@ class Connedit extends Controller {
}
if($cmd === 'refresh') {
if($orig_record[0]['xchan_network'] === 'zot') {
if(! zot_refresh($orig_record[0],App::get_channel()))
notice( t('Refresh failed - channel is currently unavailable.') );
}
elseif($orig_record[0]['xchan_network'] === 'zot6') {
if($orig_record[0]['xchan_network'] === 'zot6') {
if(! Libzot::refresh($orig_record[0],App::get_channel()))
notice( t('Refresh failed - channel is currently unavailable.') );
}
else {
// if you are on a different network we'll force a refresh of the connection basic info
Master::Summon(array('Notifier','permission_update',$contact_id));
}
@@ -667,7 +659,7 @@ class Connedit extends Controller {
);
if(in_array($contact['xchan_network'], ['zot6', 'zot'])) {
if($contact['xchan_network'] === 'zot6') {
$tools['fetchvc'] = [
'label' => t('Fetch Vcard'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc',
@@ -841,7 +833,7 @@ class Connedit extends Controller {
$locstr = unpunify($contact['xchan_url']);
$clone_warn = '';
$clonable = (in_array($contact['xchan_network'],['zot', 'zot6', 'rss']) ? true : false);
$clonable = in_array($contact['xchan_network'], ['zot6', 'rss']);
if(! $clonable) {
$clone_warn = '<strong>';
$clone_warn .= ((intval($contact['abook_not_here']))

View File

@@ -19,13 +19,13 @@ class Defperms extends Controller {
*/
function init() {
if(! local_channel())
return;
if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
return;
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_self = 1 and abook_channel = %d LIMIT 1",
@@ -37,39 +37,39 @@ class Defperms extends Controller {
$channel = App::get_channel();
if($channel)
head_set_icon($channel['xchan_photo_s']);
head_set_icon($channel['xchan_photo_s']);
}
/* @brief Evaluate posted values and set changes
*
*/
function post() {
if(! local_channel())
return;
if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
return;
$contact_id = intval(argv(1));
if(! $contact_id)
return;
$channel = App::get_channel();
$orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
intval($contact_id),
intval(local_channel())
);
if(! $orig_record) {
notice( t('Could not access contact record.') . EOL);
goaway(z_root() . '/connections');
return; // NOTREACHED
}
if(intval($orig_record[0]['abook_self'])) {
$autoperms = intval($_POST['autoperms']);
@@ -79,8 +79,8 @@ class Defperms extends Controller {
$autoperms = null;
$is_self = false;
}
$all_perms = \Zotlabs\Access\Permissions::Perms();
if($all_perms) {
@@ -105,15 +105,15 @@ class Defperms extends Controller {
}
}
if(! is_null($autoperms))
if(! is_null($autoperms))
set_pconfig($channel['channel_id'],'system','autoperms',$autoperms);
notice( t('Settings updated.') . EOL);
// Refresh the structure in memory with the new data
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
@@ -123,28 +123,28 @@ class Defperms extends Controller {
if($r) {
App::$poi = $r[0];
}
$this->defperms_clone($a);
goaway(z_root() . '/defperms');
return;
}
/* @brief Clone connection
*
*
*/
function defperms_clone(&$a) {
if(! App::$poi)
return;
$channel = App::get_channel();
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
@@ -154,30 +154,30 @@ class Defperms extends Controller {
if($r) {
App::$poi = array_shift($r);
}
$clone = App::$poi;
unset($clone['abook_id']);
unset($clone['abook_account']);
unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
if($abconfig)
$clone['abconfig'] = $abconfig;
Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
}
/* @brief Generate content of connection default permissions page
*
*
*/
function get() {
$sort_type = 0;
$o = '';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
@@ -186,17 +186,15 @@ class Defperms extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Default Permissions App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Set custom default permissions for new connections');
return $o;
$papp = Apps::get_papp('Default Permissions');
return Apps::app_render($papp, 'module');
}
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
$channel = App::get_channel();
$yes_no = array(t('No'),t('Yes'));
$connect_perms = \Zotlabs\Access\Permissions::connect_perms(local_channel());
$o .= "<script>function connectDefaultShare() {
@@ -210,28 +208,28 @@ class Defperms extends Controller {
}
}
$o .= " }\n</script>\n";
if(App::$poi) {
$sections = [];
$self = false;
$tpl = get_markup_template('defperms.tpl');
$perms = array();
$channel = App::get_channel();
$contact = App::$poi;
$global_perms = \Zotlabs\Access\Permissions::Perms();
$hidden_perms = [];
foreach($global_perms as $k => $v) {
$thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
$checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
$inherited = (($checkinherited & PERMS_SPECIFIC) ? false : true);
@@ -241,7 +239,7 @@ class Defperms extends Controller {
$hidden_perms[] = [ 'perms_' . $k, intval($thisperm) ];
}
}
$pcat = new \Zotlabs\Lib\Permcat(local_channel());
$pcatlist = $pcat->listing();
$permcats = [];
@@ -272,13 +270,13 @@ class Defperms extends Controller {
'$contact_id' => $contact['abook_id'],
'$name' => $contact['xchan_name'],
]);
$arr = array('contact' => $contact,'output' => $o);
call_hooks('contact_edit', $arr);
return $arr['output'];
}
}
}
}

View File

@@ -8,7 +8,6 @@ use Zotlabs\Lib\Libzotdir;
require_once('include/socgraph.php');
require_once('include/dir_fns.php');
require_once('include/bbcode.php');
require_once('include/html2plain.php');

View File

@@ -4,26 +4,22 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
require_once('include/dir_fns.php');
class Dirsearch extends Controller {
function init() {
App::set_pager_itemspage(30);
}
function get() {
$ret = array('success' => false);
// logger('request: ' . print_r($_REQUEST,true));
$dirmode = intval(get_config('system','directory_mode'));
if($dirmode == DIRECTORY_MODE_NORMAL) {
$ret['message'] = t('This site is not a directory server');
json_return_and_die($ret);
@@ -31,24 +27,24 @@ class Dirsearch extends Controller {
$access_token = $_REQUEST['t'];
$token = get_config('system','realm_token');
if($token && $access_token != $token) {
$ret['message'] = t('This directory server requires an access token');
json_return_and_die($ret);
}
if(argc() > 1 && argv(1) === 'sites') {
$ret = $this->list_public_sites();
json_return_and_die($ret);
}
$sql_extra = '';
$tables = array('name','address','locale','region','postcode','country','gender','marital','sexual','keywords');
if($_REQUEST['query']) {
$advanced = $this->dir_parse_query($_REQUEST['query']);
if($advanced) {
@@ -64,9 +60,9 @@ class Dirsearch extends Controller {
}
}
}
$hash = ((x($_REQUEST['hash'])) ? $_REQUEST['hash'] : '');
$name = ((x($_REQUEST,'name')) ? $_REQUEST['name'] : '');
$hub = ((x($_REQUEST,'hub')) ? $_REQUEST['hub'] : '');
$address = ((x($_REQUEST,'address')) ? $_REQUEST['address'] : '');
@@ -82,16 +78,16 @@ class Dirsearch extends Controller {
$agele = ((x($_REQUEST,'agele')) ? intval($_REQUEST['agele']) : 0 );
$kw = ((x($_REQUEST,'kw')) ? intval($_REQUEST['kw']) : 0 );
$forums = ((array_key_exists('pubforums',$_REQUEST)) ? intval($_REQUEST['pubforums']) : 0);
if(get_config('system','disable_directory_keywords'))
$kw = 0;
// by default use a safe search
$safe = ((x($_REQUEST,'safe'))); // ? intval($_REQUEST['safe']) : 1 );
if ($safe === false)
$safe = 1;
if(array_key_exists('sync',$_REQUEST)) {
if($_REQUEST['sync'])
$sync = datetime_convert('UTC','UTC',$_REQUEST['sync']);
@@ -100,7 +96,7 @@ class Dirsearch extends Controller {
}
else
$sync = false;
if(($dirmode == DIRECTORY_MODE_STANDALONE) && (! $hub)) {
$hub = \App::get_hostname();
}
@@ -109,13 +105,13 @@ class Dirsearch extends Controller {
$hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
else
$hub_query = '';
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : '');
$joiner = ' OR ';
if($_REQUEST['and'])
$joiner = ' AND ';
if($name)
$sql_extra .= $this->dir_query_build($joiner,'xchan_name',$name);
if($address)
@@ -136,58 +132,58 @@ class Dirsearch extends Controller {
$sql_extra .= $this->dir_query_build($joiner,'xprof_sexual',$sexual);
if($keywords)
$sql_extra .= $this->dir_query_build($joiner,'xprof_keywords',$keywords);
// we only support an age range currently. You must set both agege
// (greater than or equal) and agele (less than or equal)
// we only support an age range currently. You must set both agege
// (greater than or equal) and agele (less than or equal)
if($agele && $agege) {
$sql_extra .= " $joiner ( xprof_age <= " . intval($agele) . " ";
$sql_extra .= " AND xprof_age >= " . intval($agege) . ") ";
}
if($hash) {
$sql_extra = " AND xchan_hash like '" . dbesc($hash) . protect_sprintf('%') . "' ";
}
$perpage = (($_REQUEST['n']) ? $_REQUEST['n'] : 60);
$page = (($_REQUEST['p']) ? intval($_REQUEST['p'] - 1) : 0);
$startrec = (($page+1) * $perpage) - $perpage;
$limit = (($_REQUEST['limit']) ? intval($_REQUEST['limit']) : 0);
$return_total = ((x($_REQUEST,'return_total')) ? intval($_REQUEST['return_total']) : 0);
// mtime is not currently working
$mtime = ((x($_REQUEST,'mtime')) ? datetime_convert('UTC','UTC',$_REQUEST['mtime']) : '');
// ok a separate tag table won't work.
// ok a separate tag table won't work.
// merge them into xprof
$ret['success'] = true;
// If &limit=n, return at most n entries
// If &return_total=1, we count matching entries and return that as 'total_items' for use in pagination.
// By default we return one page (default 80 items maximum) and do not count total entries
$logic = ((strlen($sql_extra)) ? 'false' : 'true');
if($hash)
$logic = 'true';
if($dirmode == DIRECTORY_MODE_STANDALONE) {
$sql_extra .= " and xchan_addr like '%%" . \App::get_hostname() . "' ";
}
$safesql = (($safe > 0) ? " and xchan_censored = 0 and xchan_selfcensored = 0 " : '');
if($safe < 0)
$safesql = " and ( xchan_censored = 1 OR xchan_selfcensored = 1 ) ";
if($forums)
$safesql .= " and xchan_pubforum = " . ((intval($forums)) ? '1 ' : '0 ');
if($limit)
if($limit)
$qlimit = " LIMIT $limit ";
else {
$qlimit = " LIMIT " . intval($perpage) . " OFFSET " . intval($startrec);
@@ -198,27 +194,27 @@ class Dirsearch extends Controller {
}
}
}
if($sort_order == 'normal') {
$order = " order by xchan_name asc ";
// Start the alphabetic search at 'A'
// Start the alphabetic search at 'A'
// This will make a handful of channels whose names begin with
// punctuation un-searchable in this mode
$safesql .= " and ascii(substring(xchan_name FROM 1 FOR 1)) > 64 ";
}
elseif($sort_order == 'reverse')
$order = " order by xchan_name desc ";
elseif($sort_order == 'reversedate')
$order = " order by xchan_name_date asc ";
else
else
$order = " order by xchan_name_date desc ";
if($sync) {
$spkt = array('transactions' => array());
$r = q("select * from updates where ud_date >= '%s' and ud_guid != '' order by ud_date desc",
$r = q("select * from updates where ud_date >= '%s' and ud_guid != '' and ud_addr != '' order by ud_date desc",
dbesc($sync)
);
if($r) {
@@ -228,7 +224,7 @@ class Dirsearch extends Controller {
$flags[] = 'deleted';
if($rr['ud_flags'] & UPDATE_FLAGS_FORCED)
$flags[] = 'forced';
$spkt['transactions'][] = array(
'hash' => $rr['ud_hash'],
'address' => $rr['ud_addr'],
@@ -238,87 +234,48 @@ class Dirsearch extends Controller {
);
}
}
$r = q("select * from xlink where xlink_static = 1 and xlink_updated >= '%s' ",
dbesc($sync)
);
if($r) {
$spkt['ratings'] = array();
foreach($r as $rr) {
$spkt['ratings'][] = array(
'type' => 'rating',
'encoding' => 'zot',
'channel' => $rr['xlink_xchan'],
'target' => $rr['xlink_link'],
'rating' => intval($rr['xlink_rating']),
'rating_text' => $rr['xlink_rating_text'],
'signature' => $rr['xlink_sig'],
'edited' => $rr['xlink_updated']
);
}
}
json_return_and_die($spkt);
}
else {
$r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash
where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
$safesql $order $qlimit "
$r = q("SELECT
xchan.xchan_name as name,
xchan.xchan_hash as hash,
xchan.xchan_censored as censored,
xchan.xchan_selfcensored as selfcensored,
xchan.xchan_pubforum as public_forum,
xchan.xchan_url as url,
xchan.xchan_photo_l as photo_l,
xchan.xchan_photo_m as photo,
xchan.xchan_addr as address,
xprof.xprof_desc as description,
xprof.xprof_locale as locale,
xprof.xprof_region as region,
xprof.xprof_postcode as postcode,
xprof.xprof_country as country,
xprof.xprof_dob as birthday,
xprof.xprof_age as age,
xprof.xprof_gender as gender,
xprof.xprof_marital as marital,
xprof.xprof_sexual as sexual,
xprof.xprof_about as about,
xprof.xprof_homepage as homepage,
xprof.xprof_hometown as hometown,
xprof.xprof_keywords as keywords
from xchan left join xprof on xchan_hash = xprof_hash left join hubloc on hubloc_hash = xchan_hash
where hubloc_primary = 1 and hubloc_updated > %s - INTERVAL %s and ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
$safesql $order $qlimit",
db_utcnow(),
db_quoteinterval('30 DAY')
);
$ret['page'] = $page + 1;
$ret['records'] = count($r);
}
if($r) {
$entries = array();
foreach($r as $rr) {
$entry = array();
$pc = q("select count(xlink_rating) as total_ratings from xlink where xlink_link = '%s' and xlink_rating != 0 and xlink_static = 1 group by xlink_rating",
dbesc($rr['xchan_hash'])
);
if($pc)
$entry['total_ratings'] = intval($pc[0]['total_ratings']);
else
$entry['total_ratings'] = 0;
$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'];
$entries[] = $entry;
}
$ret['results'] = $entries;
$ret['results'] = $r;
$ret['page'] = $page + 1;
$ret['records'] = count($r);
if($kw) {
$k = dir_tagadelic($kw, $hub);
if($k) {
@@ -328,30 +285,30 @@ class Dirsearch extends Controller {
}
}
}
}
}
json_return_and_die($ret);
}
function dir_query_build($joiner,$field,$s) {
$ret = '';
if(trim($s))
$ret .= dbesc($joiner) . " " . dbesc($field) . " like '" . protect_sprintf( '%' . dbesc($s) . '%' ) . "' ";
return $ret;
}
function dir_flag_build($joiner,$field,$bit,$s) {
return dbesc($joiner) . " ( " . dbesc($field) . " & " . intval($bit) . " ) " . ((intval($s)) ? '>' : '=' ) . " 0 ";
}
function dir_parse_query($s) {
$ret = array();
$curr = array();
$all = explode(' ',$s);
$quoted_string = false;
if($all) {
foreach($all as $q) {
if($quoted_string === false) {
@@ -382,7 +339,7 @@ class Dirsearch extends Controller {
$ret[] = $curr;
$curr = array();
continue;
}
}
else {
$ret[] = $curr;
$curr = array();
@@ -405,15 +362,15 @@ class Dirsearch extends Controller {
logger('dir_parse_query:' . print_r($ret,true),LOGGER_DATA);
return $ret;
}
function list_public_sites() {
$rand = db_getfunc('rand');
$realm = get_directory_realm();
if($realm == DIRECTORY_REALM) {
@@ -428,16 +385,16 @@ class Dirsearch extends Controller {
intval(SITE_TYPE_ZOT)
);
}
$ret = array('success' => false);
if($r) {
$ret['success'] = true;
$ret['sites'] = array();
$insecure = array();
foreach($r as $rr) {
if($rr['site_access'] == ACCESS_FREE)
$access = 'free';
elseif($rr['site_access'] == ACCESS_PAID)
@@ -446,14 +403,14 @@ class Dirsearch extends Controller {
$access = 'tiered';
else
$access = 'private';
if($rr['site_register'] == REGISTER_OPEN)
$register = 'open';
elseif($rr['site_register'] == REGISTER_APPROVE)
$register = 'approve';
else
$register = 'closed';
if(strpos($rr['site_url'],'https://') !== false)
$ret['sites'][] = array('url' => $rr['site_url'], 'access' => $access, 'register' => $register, 'sellpage' => $rr['site_sellpage'], 'location' => $rr['site_location'], 'project' => $rr['site_project'], 'version' => $rr['site_version']);
else

View File

@@ -1,6 +1,8 @@
<?php
namespace Zotlabs\Module;
use App;
require_once("include/bbcode.php");
require_once('include/security.php');
require_once('include/conversation.php');
@@ -34,11 +36,20 @@ class Display extends \Zotlabs\Web\Controller {
}
}
if($_REQUEST['mid'])
if($_REQUEST['mid']) {
$item_hash = $_REQUEST['mid'];
}
if(! $item_hash) {
\App::$error = 404;
$item_hash = unpack_link_id($item_hash);
if ($item_hash === false) {
App::$error = 400;
notice(t('Malformed message id.') . EOL);
return;
}
if(!$item_hash) {
App::$error = 404;
notice( t('Item not found.') . EOL);
return;
}
@@ -47,7 +58,7 @@ class Display extends \Zotlabs\Web\Controller {
if(local_channel() && (! $update)) {
$channel = \App::get_channel();
$channel = App::get_channel();
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
@@ -92,11 +103,6 @@ class Display extends \Zotlabs\Web\Controller {
$target_item = null;
if(strpos($item_hash,'b64.') === 0)
$decoded = @base64url_decode(substr($item_hash,4));
if($decoded)
$item_hash = $decoded;
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid = '%s' limit 1",
dbesc($item_hash)
);
@@ -110,7 +116,7 @@ class Display extends \Zotlabs\Web\Controller {
);
if($x) {
// not yet ready for prime time
// \App::$poi = $x[0];
// App::$poi = $x[0];
}
//if the item is to be moderated redirect to /moderate
@@ -189,17 +195,15 @@ 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['mid'];
// if we got a decoded hash we must encode it again before handing to javascript
if($decoded)
$mid = 'b64.' . base64url_encode($mid);
$mid = gen_link_id($target_item['mid']);
$o .= '<div id="live-display"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; </script>\r\n";
. "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'display',
'$uid' => '0',
@@ -215,7 +219,7 @@ class Display extends \Zotlabs\Web\Controller {
'$dm' => '0',
'$nouveau' => '0',
'$wall' => '0',
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$search' => '',
'$xchan' => '',
@@ -233,7 +237,7 @@ class Display extends \Zotlabs\Web\Controller {
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
'title' => 'oembed'
]);
@@ -355,7 +359,7 @@ class Display extends \Zotlabs\Web\Controller {
}
$o .= '</noscript>';
\App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . \App::$page['title'] : \App::$page['title']);
App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . App::$page['title'] : App::$page['title']);
$o .= conversation($items, 'display', $update, 'client');
}
@@ -368,12 +372,12 @@ class Display extends \Zotlabs\Web\Controller {
'$version' => xmlify(\Zotlabs\Lib\System::get_project_version()),
'$generator' => xmlify(\Zotlabs\Lib\System::get_platform_name()),
'$generator_uri' => 'https://hubzilla.org',
'$feed_id' => xmlify(\App::$cmd),
'$feed_id' => xmlify(App::$cmd),
'$feed_title' => xmlify(t('Article')),
'$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now', ATOM_TIME)),
'$author' => '',
'$owner' => '',
'$profile_page' => xmlify(z_root() . '/display/' . $target_item['mid']),
'$profile_page' => xmlify(z_root() . '/display/' . gen_link_id($target_item['mid'])),
));
$x = [ 'xml' => $atom, 'channel' => $channel, 'observer_hash' => $observer_hash, 'params' => $params ];

View File

@@ -5,33 +5,21 @@ namespace Zotlabs\Module;
class Dreport extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return;
}
$table = 'item';
$channel = \App::get_channel();
$mid = ((argc() > 1) ? argv(1) : '');
$encoded_mid = '';
if(strpos($mid,'b64.') === 0) {
$encoded_mid = $mid;
$mid = @base64url_decode(substr($mid,4));
}
$table = 'item';
$channel = \App::get_channel();
$mid = ((argc() > 1) ? unpack_link_id(argv(1)) : '');
if($mid === 'push') {
$table = 'push';
$mid = ((argc() > 2) ? argv(2) : '');
$mid = ((argc() > 2) ? unpack_link_id(argv(2)) : '');
if(strpos($mid,'b64.') === 0) {
$encoded_mid = $mid;
$mid = @base64url_decode(substr($mid,4));
}
if($mid) {
if($mid) {
$i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
dbesc($mid),
intval($channel['channel_id']),
@@ -43,23 +31,14 @@ class Dreport extends \Zotlabs\Web\Controller {
}
}
sleep(3);
goaway(z_root() . '/dreport/' . (($encoded_mid) ? $encoded_mid : $mid));
goaway(z_root() . '/dreport/' . gen_link_id($mid));
}
if($mid === 'mail') {
$table = 'mail';
$mid = ((argc() > 2) ? argv(2) : '');
if(strpos($mid,'b64.') === 0)
$mid = @base64url_decode(substr($mid,4));
}
if(! $mid) {
notice( t('Invalid message') . EOL);
return;
}
switch($table) {
case 'item':
$i = q("select id from item where mid = '%s' and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
@@ -68,39 +47,32 @@ class Dreport extends \Zotlabs\Web\Controller {
dbesc($channel['channel_hash'])
);
break;
case 'mail':
$i = q("select id from mail where mid = '%s' and from_xchan = '%s'",
dbesc($mid),
dbesc($channel['channel_hash'])
);
break;
default:
break;
}
if(! $i) {
notice( t('Permission denied') . EOL);
return;
}
$r = q("select * from dreport where (dreport_xchan = '%s' or dreport_xchan = '%s') and dreport_mid = '%s'",
$r = q("select * from dreport where dreport_xchan = '%s' and dreport_mid = '%s'",
dbesc($channel['channel_hash']),
dbesc($channel['channel_portable_id']),
dbesc($mid)
);
if(! $r) {
notice( t('no results') . EOL);
// return;
}
for($x = 0; $x < count($r); $x++ ) {
// This has two purposes: 1. make the delivery report strings translateable, and
// 2. assign an ordering to item delivery results so we can group them and provide
// a readable report with more interesting events listed toward the top and lesser
// interesting items towards the bottom
switch($r[$x]['dreport_result']) {
case 'channel sync processed':
$r[$x]['gravity'] = 0;
@@ -132,27 +104,18 @@ class Dreport extends \Zotlabs\Web\Controller {
case 'recipient not found':
$r[$x]['dreport_result'] = t('recipient not found');
break;
case 'mail recalled':
$r[$x]['dreport_result'] = t('mail recalled');
break;
case 'duplicate mail received':
$r[$x]['dreport_result'] = t('duplicate mail received');
break;
case 'mail delivered':
$r[$x]['dreport_result'] = t('mail delivered');
break;
default:
$r[$x]['gravity'] = 1;
break;
}
}
usort($r,'self::dreport_gravity_sort');
$entries = array();
foreach($r as $rr) {
$entries[] = [
'name' => escape_tags($rr['dreport_name'] ?: $rr['dreport_recip']),
$entries[] = [
'name' => escape_tags($rr['dreport_name'] ?: $rr['dreport_recip']),
'result' => escape_tags($rr['dreport_result']),
'time' => escape_tags(datetime_convert('UTC',date_default_timezone_get(),$rr['dreport_time']))
];
@@ -167,14 +130,14 @@ class Dreport extends \Zotlabs\Web\Controller {
'$push' => t('Redeliver'),
'$entries' => $entries
));
return $o;
}
private static function dreport_gravity_sort($a,$b) {
if($a['gravity'] == $b['gravity']) {
if($a['dreport_name'] === $b['dreport_name'])
@@ -183,5 +146,5 @@ class Dreport extends \Zotlabs\Web\Controller {
}
return (($a['gravity'] > $b['gravity']) ? 1 : (-1));
}
}

View File

@@ -1,750 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/conversation.php');
require_once('include/bbcode.php');
require_once('include/datetime.php');
require_once('include/event.php');
require_once('include/items.php');
require_once('include/html2plain.php');
class Events extends \Zotlabs\Web\Controller {
function post() {
// this module is deprecated
return;
logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
if(! local_channel())
return;
if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size'])) {
$src = $_FILES['userfile']['tmp_name'];
if($src) {
$result = parse_ical_file($src,local_channel());
if($result)
info( t('Calendar entries imported.') . EOL);
else
notice( t('No calendar entries found.') . EOL);
@unlink($src);
}
goaway(z_root() . '/events');
}
$event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0);
$event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : '');
$xchan = ((x($_POST,'xchan')) ? dbesc($_POST['xchan']) : '');
$uid = local_channel();
$start_text = escape_tags($_REQUEST['start_text']);
$finish_text = escape_tags($_REQUEST['finish_text']);
$adjust = intval($_POST['adjust']);
$nofinish = intval($_POST['nofinish']);
$timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
$tz = (($timezone) ? $timezone : date_default_timezone_get());
$categories = escape_tags(trim($_POST['category']));
// only allow editing your own events.
if(($xchan) && ($xchan !== get_observer_hash()))
return;
if($start_text) {
$start = $start_text;
}
else {
$start = sprintf('%d-%d-%d %d:%d:0',$startyear,$startmonth,$startday,$starthour,$startminute);
}
if($finish_text) {
$finish = $finish_text;
}
else {
$finish = sprintf('%d-%d-%d %d:%d:0',$finishyear,$finishmonth,$finishday,$finishhour,$finishminute);
}
if($nofinish) {
$finish = NULL_DATE;
}
if($adjust) {
$start = datetime_convert($tz,'UTC',$start);
if(! $nofinish)
$finish = datetime_convert($tz,'UTC',$finish);
}
else {
$start = datetime_convert('UTC','UTC',$start);
if(! $nofinish)
$finish = datetime_convert('UTC','UTC',$finish);
}
// Don't allow the event to finish before it begins.
// It won't hurt anything, but somebody will file a bug report
// and we'll waste a bunch of time responding to it. Time that
// could've been spent doing something else.
$summary = escape_tags(trim($_POST['summary']));
$desc = escape_tags(trim($_POST['desc']));
$location = escape_tags(trim($_POST['location']));
$type = escape_tags(trim($_POST['type']));
require_once('include/text.php');
linkify_tags($desc, local_channel());
linkify_tags($location, local_channel());
//$action = ($event_hash == '') ? 'new' : "event/" . $event_hash;
//fixme: this url gives a wsod if there is a linebreak detected in one of the variables ($desc or $location)
//$onerror_url = z_root() . "/events/" . $action . "?summary=$summary&description=$desc&location=$location&start=$start_text&finish=$finish_text&adjust=$adjust&nofinish=$nofinish&type=$type";
$onerror_url = z_root() . "/events";
if(strcmp($finish,$start) < 0 && !$nofinish) {
notice( t('Event can not end before it has started.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Unable to generate preview.'));
killme();
}
goaway($onerror_url);
}
if((! $summary) || (! $start)) {
notice( t('Event title and start time are required.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Unable to generate preview.'));
killme();
}
goaway($onerror_url);
}
// $share = ((intval($_POST['distr'])) ? intval($_POST['distr']) : 0);
$share = 1;
$channel = \App::get_channel();
$acl = new \Zotlabs\Access\AccessList(false);
if($event_id) {
$x = q("select * from event where id = %d and uid = %d limit 1",
intval($event_id),
intval(local_channel())
);
if(! $x) {
notice( t('Event not found.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Unable to generate preview.'));
killme();
}
return;
}
$acl->set($x[0]);
$created = $x[0]['created'];
$edited = datetime_convert();
if($x[0]['allow_cid'] === '<' . $channel['channel_hash'] . '>'
&& $x[0]['allow_gid'] === '' && $x[0]['deny_cid'] === '' && $x[0]['deny_gid'] === '') {
$share = false;
}
else {
$share = true;
}
}
else {
$created = $edited = datetime_convert();
if($share) {
$acl->set_from_array($_POST);
}
else {
$acl->set(array('allow_cid' => '<' . $channel['channel_hash'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''));
}
}
$post_tags = array();
$channel = \App::get_channel();
$ac = $acl->get();
if(strlen($categories)) {
$cats = explode(',',$categories);
foreach($cats as $cat) {
$post_tags[] = array(
'uid' => $profile_uid,
'ttype' => TERM_CATEGORY,
'otype' => TERM_OBJ_POST,
'term' => trim($cat),
'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
);
}
}
$datarray = array();
$datarray['dtstart'] = $start;
$datarray['dtend'] = $finish;
$datarray['summary'] = $summary;
$datarray['description'] = $desc;
$datarray['location'] = $location;
$datarray['etype'] = $type;
$datarray['adjust'] = $adjust;
$datarray['nofinish'] = $nofinish;
$datarray['uid'] = local_channel();
$datarray['account'] = get_account_id();
$datarray['event_xchan'] = $channel['channel_hash'];
$datarray['allow_cid'] = $ac['allow_cid'];
$datarray['allow_gid'] = $ac['allow_gid'];
$datarray['deny_cid'] = $ac['deny_cid'];
$datarray['deny_gid'] = $ac['deny_gid'];
$datarray['private'] = (($acl->is_private()) ? 1 : 0);
$datarray['id'] = $event_id;
$datarray['created'] = $created;
$datarray['edited'] = $edited;
if(intval($_REQUEST['preview'])) {
$html = format_event_html($datarray);
echo $html;
killme();
}
$event = event_store_event($datarray);
if($post_tags)
$datarray['term'] = $post_tags;
$item_id = event_store_item($datarray,$event);
if($item_id) {
$r = q("select * from item where id = %d",
intval($item_id)
);
if($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
$z = q("select * from event where event_hash = '%s' and uid = %d limit 1",
dbesc($r[0]['resource_id']),
intval($channel['channel_id'])
);
if($z) {
build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
}
}
}
if($share)
\Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
}
function get() {
// this module is deprecated
return;
if(argc() > 2 && argv(1) == 'ical') {
$event_id = argv(2);
require_once('include/security.php');
$sql_extra = permissions_sql(local_channel());
$r = q("select * from event where event_hash = '%s' $sql_extra limit 1",
dbesc($event_id)
);
if($r) {
header('Content-type: text/calendar');
header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"' );
echo ical_wrapper($r);
killme();
}
else {
notice( t('Event not found.') . EOL );
return;
}
}
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
\App::$profile_uid = local_channel();
nav_set_selected('Events');
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
$r = q("update event set dismissed = 1 where id = %d and uid = %d",
intval(argv(2)),
intval(local_channel())
);
}
if((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) {
$r = q("update event set dismissed = 0 where id = %d and uid = %d",
intval(argv(2)),
intval(local_channel())
);
}
$first_day = feature_enabled(local_channel(), 'events_cal_first_day');
$first_day = (($first_day) ? $first_day : 0);
$htpl = get_markup_template('event_head.tpl');
\App::$page['htmlhead'] .= replace_macros($htpl,array(
'$baseurl' => z_root(),
'$module_url' => '/events',
'$modparams' => 1,
'$lang' => \App::$language,
'$first_day' => $first_day
));
$o = '';
$channel = \App::get_channel();
$mode = 'view';
$y = 0;
$m = 0;
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
// logger('args: ' . print_r(\App::$argv,true));
if(argc() > 1) {
if(argc() > 2 && argv(1) === 'add') {
$mode = 'add';
$item_id = intval(argv(2));
}
if(argc() > 2 && argv(1) === 'drop') {
$mode = 'drop';
$event_id = argv(2);
}
if(argc() > 2 && intval(argv(1)) && intval(argv(2))) {
$mode = 'view';
$y = intval(argv(1));
$m = intval(argv(2));
}
if(argc() <= 2) {
$mode = 'view';
$event_id = argv(1);
}
}
if($mode === 'add') {
event_addtocal($item_id,local_channel());
killme();
}
if($mode == 'view') {
/* edit/create form */
if($event_id) {
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
dbesc($event_id),
intval(local_channel())
);
if(count($r))
$orig_event = $r[0];
}
$channel = \App::get_channel();
// Passed parameters overrides anything found in the DB
if(!x($orig_event))
$orig_event = array();
// In case of an error the browser is redirected back here, with these parameters filled in with the previous values
/*
if(x($_REQUEST,'nofinish')) $orig_event['nofinish'] = $_REQUEST['nofinish'];
if(x($_REQUEST,'adjust')) $orig_event['adjust'] = $_REQUEST['adjust'];
if(x($_REQUEST,'summary')) $orig_event['summary'] = $_REQUEST['summary'];
if(x($_REQUEST,'description')) $orig_event['description'] = $_REQUEST['description'];
if(x($_REQUEST,'location')) $orig_event['location'] = $_REQUEST['location'];
if(x($_REQUEST,'start')) $orig_event['dtstart'] = $_REQUEST['start'];
if(x($_REQUEST,'finish')) $orig_event['dtend'] = $_REQUEST['finish'];
if(x($_REQUEST,'type')) $orig_event['etype'] = $_REQUEST['type'];
*/
$n_checked = ((x($orig_event) && $orig_event['nofinish']) ? ' checked="checked" ' : '');
$a_checked = ((x($orig_event) && $orig_event['adjust']) ? ' checked="checked" ' : '');
$t_orig = ((x($orig_event)) ? $orig_event['summary'] : '');
$d_orig = ((x($orig_event)) ? $orig_event['description'] : '');
$l_orig = ((x($orig_event)) ? $orig_event['location'] : '');
$eid = ((x($orig_event)) ? $orig_event['id'] : 0);
$event_xchan = ((x($orig_event)) ? $orig_event['event_xchan'] : $channel['channel_hash']);
$mid = ((x($orig_event)) ? $orig_event['mid'] : '');
if(! x($orig_event)) {
$sh_checked = '';
$a_checked = ' checked="checked" ';
}
else {
$sh_checked = ((($orig_event['allow_cid'] === '<' . $channel['channel_hash'] . '>' || (! $orig_event['allow_cid'])) && (! $orig_event['allow_gid']) && (! $orig_event['deny_cid']) && (! $orig_event['deny_gid'])) ? '' : ' checked="checked" ' );
}
if($orig_event['event_xchan'])
$sh_checked .= ' disabled="disabled" ';
$sdt = ((x($orig_event)) ? $orig_event['dtstart'] : 'now');
$fdt = ((x($orig_event)) ? $orig_event['dtend'] : '+1 hour');
$tz = date_default_timezone_get();
if(x($orig_event))
$tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC');
$syear = datetime_convert('UTC', $tz, $sdt, 'Y');
$smonth = datetime_convert('UTC', $tz, $sdt, 'm');
$sday = datetime_convert('UTC', $tz, $sdt, 'd');
$shour = datetime_convert('UTC', $tz, $sdt, 'H');
$sminute = datetime_convert('UTC', $tz, $sdt, 'i');
$stext = datetime_convert('UTC',$tz,$sdt);
$stext = substr($stext,0,14) . "00:00";
$fyear = datetime_convert('UTC', $tz, $fdt, 'Y');
$fmonth = datetime_convert('UTC', $tz, $fdt, 'm');
$fday = datetime_convert('UTC', $tz, $fdt, 'd');
$fhour = datetime_convert('UTC', $tz, $fdt, 'H');
$fminute = datetime_convert('UTC', $tz, $fdt, 'i');
$ftext = datetime_convert('UTC',$tz,$fdt);
$ftext = substr($ftext,0,14) . "00:00";
$type = ((x($orig_event)) ? $orig_event['etype'] : 'event');
$f = get_config('system','event_input_format');
if(! $f)
$f = 'ymd';
$catsenabled = feature_enabled(local_channel(),'categories');
$category = '';
if($catsenabled && x($orig_event)){
$itm = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d limit 1",
dbesc($orig_event['event_hash']),
intval(local_channel())
);
$itm = fetch_post_tags($itm);
if($itm) {
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if(strlen($category))
$category .= ', ';
$category .= $cat['term'];
}
}
}
require_once('include/acl_selectors.php');
$acl = new \Zotlabs\Access\AccessList($channel);
$perm_defaults = $acl->get();
$permissions = ((x($orig_event)) ? $orig_event : $perm_defaults);
$tpl = get_markup_template('event_form.tpl');
$form = replace_macros($tpl,array(
'$post' => z_root() . '/events',
'$eid' => $eid,
'$type' => $type,
'$xchan' => $event_xchan,
'$mid' => $mid,
'$event_hash' => $event_id,
'$summary' => array('summary', (($event_id) ? t('Edit event title') : t('Event title')), $t_orig, t('Required'), '*'),
'$catsenabled' => $catsenabled,
'$placeholdercategory' => t('Categories (comma-separated list)'),
'$c_text' => (($event_id) ? t('Edit Category') : t('Category')),
'$category' => $category,
'$required' => '<span class="required" title="' . t('Required') . '">*</span>',
'$s_dsel' => datetimesel($f,new \DateTime(),\DateTime::createFromFormat('Y',$syear+5),\DateTime::createFromFormat('Y-m-d H:i',"$syear-$smonth-$sday $shour:$sminute"), (($event_id) ? t('Edit start date and time') : t('Start date and time')), 'start_text',true,true,'','',true,$first_day),
'$n_text' => t('Finish date and time are not known or not relevant'),
'$n_checked' => $n_checked,
'$f_dsel' => datetimesel($f,new \DateTime(),\DateTime::createFromFormat('Y',$fyear+5),\DateTime::createFromFormat('Y-m-d H:i',"$fyear-$fmonth-$fday $fhour:$fminute"), (($event_id) ? t('Edit finish date and time') : t('Finish date and time')),'finish_text',true,true,'start_text','',false,$first_day),
'$nofinish' => array('nofinish', t('Finish date and time are not known or not relevant'), $n_checked, '', array(t('No'),t('Yes')), 'onclick="enableDisableFinishDate();"'),
'$adjust' => array('adjust', t('Adjust for viewer timezone'), $a_checked, t('Important for events that happen in a particular place. Not practical for global holidays.'), array(t('No'),t('Yes'))),
'$a_text' => t('Adjust for viewer timezone'),
'$d_text' => (($event_id) ? t('Edit Description') : t('Description')),
'$d_orig' => $d_orig,
'$l_text' => (($event_id) ? t('Edit Location') : t('Location')),
'$l_orig' => $l_orig,
'$t_orig' => $t_orig,
'$preview' => t('Preview'),
'$perms_label' => t('Permission settings'),
// populating the acl dialog was a permission description from view_stream because Cal.php, which
// displays events, says "since we don't currently have an event permission - use the stream permission"
'$acl' => (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults), false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'))),
'$allow_cid' => acl2json($permissions['allow_cid']),
'$allow_gid' => acl2json($permissions['allow_gid']),
'$deny_cid' => acl2json($permissions['deny_cid']),
'$deny_gid' => acl2json($permissions['deny_gid']),
'$tz_choose' => feature_enabled(local_channel(),'event_tz_select'),
'$timezone' => array('timezone_select' , t('Timezone:'), date_default_timezone_get(), '', get_timezones()),
'$lockstate' => (($acl->is_private()) ? 'lock' : 'unlock'),
'$submit' => t('Submit'),
'$advanced' => t('Advanced Options')
));
/* end edit/create form */
$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
if(! $y)
$y = intval($thisyear);
if(! $m)
$m = intval($thismonth);
$export = false;
if(argc() === 4 && argv(3) === 'export')
$export = true;
// Put some limits on dates. The PHP date functions don't seem to do so well before 1900.
// An upper limit was chosen to keep search engines from exploring links millions of years in the future.
if($y < 1901)
$y = 1900;
if($y > 2099)
$y = 2100;
$nextyear = $y;
$nextmonth = $m + 1;
if($nextmonth > 12) {
$nextmonth = 1;
$nextyear ++;
}
$prevyear = $y;
if($m > 1)
$prevmonth = $m - 1;
else {
$prevmonth = 12;
$prevyear --;
}
$dim = get_dim($y,$m);
$start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0);
$finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59);
if (argv(1) === 'json'){
if (x($_GET,'start')) $start = $_GET['start'];
if (x($_GET,'end')) $finish = $_GET['end'];
}
$start = datetime_convert('UTC','UTC',$start);
$finish = datetime_convert('UTC','UTC',$finish);
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
if (x($_GET,'id')){
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d limit 1",
intval(local_channel()),
intval($_GET['id'])
);
} elseif($export) {
$r = q("SELECT * from event where uid = %d
AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )
OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) ",
intval(local_channel()),
dbesc($start),
dbesc($finish),
dbesc($adjust_start),
dbesc($adjust_finish)
);
}
else {
// fixed an issue with "nofinish" events not showing up in the calendar.
// There's still an issue if the finish date crosses the end of month.
// Noting this for now - it will need to be fixed here and in Friendica.
// Ultimately the finish date shouldn't be involved in the query.
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
from event left join item on event_hash = resource_id
where resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored
AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )
OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) ",
intval(local_channel()),
dbesc($start),
dbesc($finish),
dbesc($adjust_start),
dbesc($adjust_finish)
);
}
$links = array();
if($r && ! $export) {
xchan_query($r);
$r = fetch_post_tags($r,true);
$r = sort_by_date($r);
}
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
if(! x($links,$j))
$links[$j] = z_root() . '/' . \App::$cmd . '#link-' . $j;
}
}
$events=array();
$last_date = '';
$fmt = t('l, F j');
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
$d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], $fmt) : datetime_convert('UTC','UTC',$rr['dtstart'],$fmt));
$d = day_translate($d);
$start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'c') : datetime_convert('UTC','UTC',$rr['dtstart'],'c'));
if ($rr['nofinish']){
$end = null;
} else {
$end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c'));
// give a fake end to birthdays so they get crammed into a
// single day on the calendar
if($rr['etype'] === 'birthday')
$end = null;
}
$is_first = ($d !== $last_date);
$last_date = $d;
$edit = ((local_channel() && $rr['author_xchan'] == get_observer_hash()) ? array(z_root().'/events/'.$rr['event_hash'].'?expandform=1',t('Edit event'),'','') : false);
$drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'','');
$title = strip_tags(html_entity_decode(zidify_links(bbcode($rr['summary'])),ENT_QUOTES,'UTF-8'));
if(! $title) {
list($title, $_trash) = explode("<br",bbcode($rr['desc']),2);
$title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8'));
}
$html = format_event_html($rr);
$rr['desc'] = zidify_links(smilies(bbcode($rr['desc'])));
$rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8',false);
$rr['location'] = zidify_links(smilies(bbcode($rr['location'])));
$events[] = array(
'id'=>$rr['id'],
'hash' => $rr['event_hash'],
'start'=> $start,
'end' => $end,
'drop' => $drop,
'allDay' => false,
'title' => $title,
'j' => $j,
'd' => $d,
'edit' => $edit,
'is_first'=>$is_first,
'item'=>$rr,
'html'=>$html,
'plink' => array($rr['plink'],t('Link to Source'),'',''),
);
}
}
if($export) {
header('Content-type: text/calendar');
header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
echo ical_wrapper($r);
killme();
}
if (\App::$argv[1] === 'json'){
echo json_encode($events); killme();
}
// links: array('href', 'text', 'extra css classes', 'title')
if (x($_GET,'id')){
$tpl = get_markup_template("event.tpl");
}
else {
$tpl = get_markup_template("events-js.tpl");
}
$o = replace_macros($tpl, array(
'$baseurl' => z_root(),
'$new_event' => array(z_root().'/events',(($event_id) ? t('Edit Event') : t('Create Event')),'',''),
'$previus' => array(z_root()."/events/$prevyear/$prevmonth",t('Previous'),'',''),
'$next' => array(z_root()."/events/$nextyear/$nextmonth",t('Next'),'',''),
'$export' => array(z_root()."/events/$y/$m/export",t('Export'),'',''),
'$calendar' => cal($y,$m,$links, ' eventcal'),
'$events' => $events,
'$view_label' => t('View'),
'$month' => t('Month'),
'$week' => t('Week'),
'$day' => t('Day'),
'$prev' => t('Previous'),
'$next' => t('Next'),
'$today' => t('Today'),
'$form' => $form,
'$expandform' => ((x($_GET,'expandform')) ? true : false),
));
if (x($_GET,'id')){ echo $o; killme(); }
return $o;
}
if($mode === 'drop' && $event_id) {
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
dbesc($event_id),
intval(local_channel())
);
$sync_event = $r[0];
if($r) {
$r = q("delete from event where event_hash = '%s' and uid = %d",
dbesc($event_id),
intval(local_channel())
);
if($r) {
$r = q("update item set resource_type = '', resource_id = '' where resource_type = 'event' and resource_id = '%s' and uid = %d",
dbesc($event_id),
intval(local_channel())
);
$sync_event['event_deleted'] = 1;
build_sync_packet(0,array('event' => array($sync_event)));
info( t('Event removed') . EOL);
}
else {
notice( t('Failed to remove event' ) . EOL);
}
goaway(z_root() . '/events');
}
}
}
}

View File

@@ -3,7 +3,6 @@ namespace Zotlabs\Module;
use Zotlabs\Lib\Libzot;
require_once('include/zot.php');
require_once('include/crypto.php');
/* fix missing or damaged hublocs */
@@ -59,23 +58,6 @@ class Fhublocs extends \Zotlabs\Web\Controller {
// Create a verified hub location pointing to this site.
/*
$h = hubloc_store_lowlevel(
[
'hubloc_guid' => $rr['channel_guid'],
'hubloc_guid_sig' => $rr['channel_guid_sig'],
'hubloc_hash' => $rr['channel_hash'],
'hubloc_addr' => channel_reddress($rr),
'hubloc_network' => 'zot',
'hubloc_primary' => $primary,
'hubloc_url' => z_root(),
'hubloc_url_sig' => base64url_encode(Crypto::sign(z_root(),$rr['channel_prvkey'])),
'hubloc_host' => \App::get_hostname(),
'hubloc_callback' => z_root() . '/post',
'hubloc_sitekey' => $sitekey
]
);
*/
$h = hubloc_store_lowlevel(
[
'hubloc_guid' => $rr['channel_guid'],

View File

@@ -99,6 +99,9 @@ class File_upload extends \Zotlabs\Web\Controller {
}
}
if(is_ajax())
killme();
goaway(z_root() . '/' . $_REQUEST['return_url']);
}

View File

@@ -26,7 +26,7 @@ class Group extends Controller {
}
function post() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
@@ -35,10 +35,10 @@ class Group extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
return;
}
if((argc() == 2) && (argv(1) === 'new')) {
check_form_security_token_redirectOnErr('/group/new', 'group_edit');
$name = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
$r = group_add(local_channel(),$name,$public);
@@ -49,11 +49,11 @@ class Group extends Controller {
notice( t('Could not create privacy group.') . EOL );
}
goaway(z_root() . '/group');
}
if((argc() == 2) && (intval(argv(1)))) {
check_form_security_token_redirectOnErr('/group', 'group_edit');
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval(argv(1)),
intval(local_channel())
@@ -61,12 +61,12 @@ class Group extends Controller {
if(! $r) {
notice( t('Privacy group not found.') . EOL );
goaway(z_root() . '/connections');
}
$group = $r[0];
$groupname = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
call_hooks ('privacygroup_extras_post',$hookinfo);
@@ -83,18 +83,14 @@ class Group extends Controller {
Libsync::build_sync_packet(local_channel(),null,true);
}
goaway(z_root() . '/group/' . argv(1) . '/' . argv(2));
}
return;
return;
}
function get() {
$change = false;
logger('mod_group: ' . App::$cmd,LOGGER_DEBUG);
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return;
@@ -103,12 +99,14 @@ class Group extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Privacy Groups App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Management of privacy groups');
return $o;
$papp = Apps::get_papp('Privacy Groups');
return Apps::app_render($papp, 'module');
}
logger('mod_group: ' . App::$cmd,LOGGER_DEBUG);
$change = false;
// Switch to text mode interface if we have more than 'n' contacts or group members
$switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit');
if($switchtotext === false)
@@ -166,16 +164,16 @@ class Group extends Controller {
$context = array('$submit' => t('Submit'));
$tpl = get_markup_template('group_edit.tpl');
if((argc() == 3) && (argv(1) === 'drop')) {
check_form_security_token_redirectOnErr('/group', 'group_drop', 't');
if(intval(argv(2))) {
$r = q("SELECT gname FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval(argv(2)),
intval(local_channel())
);
if($r)
if($r)
$result = group_rmv(local_channel(),$r[0]['gname']);
if($result) {
$hookinfo = [ 'pgrp_extras' => '', 'group' => argv(2) ];
@@ -188,23 +186,23 @@ class Group extends Controller {
goaway(z_root() . '/group');
// NOTREACHED
}
if((argc() > 2) && intval(argv(1)) && argv(2)) {
check_form_security_token_ForbiddenOnErr('group_member_change', 't');
$r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1",
dbesc(base64url_decode(argv(2))),
intval(local_channel())
);
if(count($r))
$change = base64url_decode(argv(2));
}
if((argc() > 1) && (intval(argv(1)))) {
require_once('include/acl_selectors.php');
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
intval(argv(1)),
@@ -215,28 +213,28 @@ class Group extends Controller {
goaway(z_root() . '/connections');
}
$group = $r[0];
$members = group_get_members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
if(! in_array($member['xchan_hash'],$preselected))
$preselected[] = $member['xchan_hash'];
}
if($change) {
if(in_array($change,$preselected)) {
group_rmv_member(local_channel(),$group['gname'],$change);
}
else {
group_add_member(local_channel(),$group['gname'],$change);
}
$members = group_get_members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
@@ -260,19 +258,19 @@ class Group extends Controller {
'$form_security_token_drop' => get_form_security_token("group_drop"),
'$pgrp_extras' => $pgrp_extras,
);
}
if(! isset($group))
return;
$groupeditor = array(
'label_members' => t('Group members'),
'members' => array(),
'label_contacts' => t('Not in this group'),
'contacts' => array(),
);
$sec_token = addslashes(get_form_security_token('group_member_change'));
$textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : 'card');
foreach($members as $member) {
@@ -284,11 +282,11 @@ class Group extends Controller {
else
group_rmv_member(local_channel(),$group['gname'],$member['xchan_hash']);
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc",
intval(local_channel())
);
if(count($r)) {
$textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : 'card');
foreach($r as $member) {
@@ -299,20 +297,20 @@ class Group extends Controller {
}
}
}
$context['$groupeditor'] = $groupeditor;
$context['$desc'] = t('Click a channel to toggle membership');
$context['$pgrp_extras'] = $pgrp_extras;
if($change) {
$tpl = get_markup_template('groupeditor.tpl');
echo replace_macros($tpl, $context);
killme();
}
return replace_macros($tpl, $context);
}
}

View File

@@ -40,7 +40,7 @@ class Home extends Controller {
if (!$dest)
$dest = get_config('system', 'startpage');
if (!$dest)
$dest = z_root() . '/network';
$dest = z_root() . '/hq';
goaway($dest);
}

View File

@@ -1,6 +1,10 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Widget\Messages;
require_once("include/bbcode.php");
require_once('include/security.php');
require_once('include/conversation.php');
@@ -14,36 +18,27 @@ class Hq extends \Zotlabs\Web\Controller {
if(! local_channel())
return;
\App::$profile_uid = local_channel();
}
function post() {
if(!local_channel())
return;
if($_REQUEST['notify_id']) {
q("update notify set seen = 1 where id = %d and uid = %d",
intval($_REQUEST['notify_id']),
intval(local_channel())
);
}
killme();
App::$profile_uid = local_channel();
}
function get($update = 0, $load = false) {
if(!local_channel())
if(!local_channel()) {
return;
if(argc() > 1 && argv(1) !== 'load') {
$item_hash = argv(1);
}
if($_REQUEST['mid'])
$item_hash = $_REQUEST['mid'];
if(argc() > 1 && argv(1) !== 'load') {
$item_hash = unpack_link_id(argv(1));
}
if(isset($_REQUEST['mid'])) {
$item_hash = unpack_link_id($_REQUEST['mid']);
}
if($item_hash === false) {
notice(t('Malformed message id.') . EOL);
return;
}
$item_normal = item_normal();
$item_normal_update = item_normal_update();
@@ -52,23 +47,17 @@ class Hq extends \Zotlabs\Web\Controller {
$r = q("SELECT mid FROM item
WHERE uid = %d $item_normal
AND mid = parent_mid
AND item_private IN (0, 1)
ORDER BY created DESC LIMIT 1",
intval(local_channel())
);
if($r[0]['mid']) {
$item_hash = 'b64.' . base64url_encode($r[0]['mid']);
$item_hash = $r[0]['mid'];
}
}
if($item_hash) {
if(strpos($item_hash,'b64.') === 0)
$decoded = @base64url_decode(substr($item_hash,4));
if($decoded)
$item_hash = $decoded;
$target_item = null;
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid = '%s' limit 1",
@@ -96,7 +85,7 @@ class Hq extends \Zotlabs\Web\Controller {
}
if(! $update) {
$channel = \App::get_channel();
$channel = App::get_channel();
$channel_acl = [
'allow_cid' => $channel['channel_allow_cid'],
@@ -125,13 +114,7 @@ class Hq extends \Zotlabs\Web\Controller {
'reset' => t('Reset form')
];
$o = replace_macros(get_markup_template("hq.tpl"),
[
'$no_messages' => (($target_item) ? false : true),
'$no_messages_label' => [ t('Welcome to Hubzilla!'), t('You have got no unseen posts...') ],
'$editor' => status_editor($a,$x,false,'Hq')
]
);
$o = status_editor($a, $x, true);
}
@@ -142,10 +125,9 @@ 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['mid'];
// if we got a decoded hash we must encode it again before handing to javascript
if($decoded)
$mid = 'b64.' . base64url_encode($mid);
$mid = gen_link_id($target_item['mid']);
}
else {
$mid = '';
@@ -153,9 +135,9 @@ class Hq extends \Zotlabs\Web\Controller {
$o .= '<div id="live-hq"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . local_channel()
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . ";</script>\r\n";
. "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . ";</script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[
'$baseurl' => z_root(),
'$pgtype' => 'hq',
'$uid' => local_channel(),
@@ -267,4 +249,16 @@ class Hq extends \Zotlabs\Web\Controller {
}
function post() {
if (!local_channel())
return;
$options['offset'] = $_REQUEST['offset'];
$options['type'] = $_REQUEST['type'];
$ret = Messages::get_messages_page($options);
json_return_and_die($ret);
}
}

View File

@@ -1,5 +1,9 @@
<?php
namespace Zotlabs\Module; /** @file */
namespace Zotlabs\Module;
use URLify;
/** @file */
// import page design element
@@ -9,33 +13,33 @@ require_once('include/menu.php');
class Impel extends \Zotlabs\Web\Controller {
function init() {
$ret = array('success' => false);
if(! local_channel())
json_return_and_die($ret);
logger('impel: ' . print_r($_REQUEST,true), LOGGER_DATA);
$elm = $_REQUEST['element'];
$x = base64url_decode($elm);
if(! $x)
json_return_and_die($ret);
$j = json_decode($x,true);
if(! $j)
json_return_and_die($ret);
// logger('element: ' . print_r($j,true));
$channel = \App::get_channel();
$arr = array();
$is_menu = false;
// a portable menu has its links rewritten with the local baseurl
$portable_menu = false;
switch($j['type']) {
case 'webpage':
$arr['item_type'] = ITEM_TYPE_WEBPAGE;
@@ -58,12 +62,12 @@ class Impel extends \Zotlabs\Web\Controller {
case 'menu':
$is_menu = true;
$installed_type = t('menu');
break;
break;
default:
logger('mod_impel: unrecognised element type' . print_r($j,true));
break;
}
if($is_menu) {
$m = array();
$m['menu_channel_id'] = local_channel();
@@ -73,23 +77,23 @@ class Impel extends \Zotlabs\Web\Controller {
$m['menu_created'] = datetime_convert($j['created']);
if($j['edited'])
$m['menu_edited'] = datetime_convert($j['edited']);
$m['menu_flags'] = 0;
if($j['flags']) {
if(in_array('bookmark',$j['flags']))
$m['menu_flags'] |= MENU_BOOKMARK;
if(in_array('system',$j['flags']))
$m['menu_flags'] |= MENU_SYSTEM;
}
$menu_id = menu_create($m);
if($menu_id) {
if(is_array($j['items'])) {
foreach($j['items'] as $it) {
$mitem = array();
$mitem['mitem_link'] = str_replace('[channelurl]',z_root() . '/channel/' . $channel['channel_address'],$it['link']);
$mitem['mitem_link'] = str_replace('[pageurl]',z_root() . '/page/' . $channel['channel_address'],$it['link']);
$mitem['mitem_link'] = str_replace('[cloudurl]',z_root() . '/cloud/' . $channel['channel_address'],$it['link']);
@@ -115,7 +119,7 @@ class Impel extends \Zotlabs\Web\Controller {
intval(local_channel())
);
}
}
}
$ret['success'] = true;
}
$x = $ret;
@@ -132,22 +136,21 @@ class Impel extends \Zotlabs\Web\Controller {
$arr['owner_xchan'] = get_observer_hash();
$arr['author_xchan'] = (($j['author_xchan']) ? $j['author_xchan'] : get_observer_hash());
$arr['mimetype'] = (($j['mimetype']) ? $j['mimetype'] : 'text/bbcode');
if(! $j['mid']) {
$j['uuid'] = item_message_id();
$j['mid'] = z_root() . '/item/' . $j['uuid'];
}
$arr['uuid'] = $j['uuid'];
$arr['mid'] = $arr['parent_mid'] = $j['mid'];
if($j['pagetitle']) {
require_once('library/urlify/URLify.php');
$pagetitle = strtolower(\URLify::transliterate($j['pagetitle']));
$pagetitle = strtolower(URLify::transliterate($j['pagetitle']));
}
// Verify ability to use html or php!!!
$execflag = ((intval($channel['channel_id']) == intval(local_channel()) && ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
$i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1",
@@ -156,7 +159,7 @@ class Impel extends \Zotlabs\Web\Controller {
);
\Zotlabs\Lib\IConfig::Set($arr,'system',$namespace,(($pagetitle) ? $pagetitle : substr($arr['mid'],0,16)),true);
if($i) {
$arr['id'] = $i[0]['id'];
// don't update if it has the same timestamp as the original
@@ -174,24 +177,24 @@ class Impel extends \Zotlabs\Web\Controller {
else
$x = item_store($arr,$execflag);
}
if($x && $x['success']) {
$item_id = $x['item_id'];
}
}
if($x['success']) {
$ret['success'] = true;
info( sprintf( t('%s element installed'), $installed_type));
info( sprintf( t('%s element installed'), $installed_type));
}
else {
notice( sprintf( t('%s element installation failed'), $installed_type));
notice( sprintf( t('%s element installation failed'), $installed_type));
}
//??? should perhaps return ret?
//??? should perhaps return ret?
json_return_and_die(true);
}
}

View File

@@ -2,14 +2,15 @@
namespace Zotlabs\Module;
require_once('include/zot.php');
require_once('include/channel.php');
require_once('include/import.php');
require_once('include/perm_upgrade.php');
require_once('library/urlify/URLify.php');
use Zotlabs\Lib\Crypto;
use App;
use URLify;
use Zotlabs\Daemon\Master;
use Zotlabs\Lib\Libzot;
use Zotlabs\Web\Controller;
/**
@@ -18,7 +19,7 @@ use Zotlabs\Lib\Libzot;
* Import a channel, either by direct file upload or via
* connection to another server.
*/
class Import extends \Zotlabs\Web\Controller {
class Import extends Controller {
/**
* @brief Import channel into account.
@@ -27,95 +28,94 @@ class Import extends \Zotlabs\Web\Controller {
*/
function import_account($account_id) {
if(! $account_id){
if (!$account_id) {
logger('No account ID supplied');
return;
}
$max_friends = account_service_class_fetch($account_id,'total_channels');
$max_feeds = account_service_class_fetch($account_id,'total_feeds');
$data = null;
$seize = ((x($_REQUEST,'make_primary')) ? intval($_REQUEST['make_primary']) : 0);
$import_posts = ((x($_REQUEST,'import_posts')) ? intval($_REQUEST['import_posts']) : 0);
$moving = intval($_REQUEST['moving']);
$src = $_FILES['filename']['tmp_name'];
$filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type'];
$newname = trim(strtolower($_REQUEST['newname']));
$max_friends = account_service_class_fetch($account_id, 'total_channels');
$max_feeds = account_service_class_fetch($account_id, 'total_feeds');
$data = null;
$seize = ((x($_REQUEST, 'make_primary')) ? intval($_REQUEST['make_primary']) : 0);
$import_posts = ((x($_REQUEST, 'import_posts')) ? intval($_REQUEST['import_posts']) : 0);
$moving = false; //intval($_REQUEST['moving']);
$src = $_FILES['filename']['tmp_name'];
$filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type'];
$newname = trim(strtolower($_REQUEST['newname']));
// import channel from file
if($src) {
if ($src) {
// This is OS specific and could also fail if your tmpdir isn't very
// large mostly used for Diaspora which exports gzipped files.
if(strpos($filename,'.gz')){
@rename($src,$src . '.gz');
if (strpos($filename, '.gz')) {
@rename($src, $src . '.gz');
@system('gunzip ' . escapeshellarg($src . '.gz'));
}
if($filesize) {
if ($filesize) {
$data = @file_get_contents($src);
}
unlink($src);
}
// import channel from another server
if(! $src) {
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
if(! $old_address) {
if (!$src) {
$old_address = ((x($_REQUEST, 'old_address')) ? $_REQUEST['old_address'] : '');
if (!$old_address) {
logger('Nothing to import.');
notice( t('Nothing to import.') . EOL);
notice(t('Nothing to import.') . EOL);
return;
} else if(strpos($old_address, '')) {
}
else if (strpos($old_address, '')) {
// if you copy the identity address from your profile page, make it work for convenience - WARNING: this is a utf-8 variant and NOT an ASCII ampersand. Please do not edit.
$old_address = str_replace('', '@', $old_address);
}
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
$email = ((x($_REQUEST, 'email')) ? $_REQUEST['email'] : '');
$password = ((x($_REQUEST, 'password')) ? $_REQUEST['password'] : '');
$channelname = substr($old_address,0,strpos($old_address,'@'));
$servername = substr($old_address,strpos($old_address,'@')+1);
$channelname = substr($old_address, 0, strpos($old_address, '@'));
$servername = substr($old_address, strpos($old_address, '@') + 1);
$api_path = probe_api_path($servername);
if(! $api_path) {
notice( t('Unable to download data from old server') . EOL);
if (!$api_path) {
notice(t('Unable to download data from old server') . EOL);
return;
}
$api_path .= 'channel/export/basic?f=&channel=' . $channelname;
if($import_posts)
$api_path .= '&posts=1';
$binary = false;
$binary = false;
$redirects = 0;
$opts = array('http_auth' => $email . ':' . $password);
$ret = z_fetch_url($api_path, $binary, $redirects, $opts);
if($ret['success']) {
$opts = ['http_auth' => $email . ':' . $password];
$ret = z_fetch_url($api_path, $binary, $redirects, $opts);
if ($ret['success']) {
$data = $ret['body'];
}
else {
notice( t('Unable to download data from old server') . EOL);
notice(t('Unable to download data from old server') . EOL);
return;
}
}
if(! $data) {
if (!$data) {
logger('Empty import file.');
notice( t('Imported file is empty.') . EOL);
notice(t('Imported file is empty.') . EOL);
return;
}
$data = json_decode($data,true);
$data = json_decode($data, true);
//logger('import: data: ' . print_r($data,true));
//print_r($data);
if(! array_key_exists('compatibility',$data)) {
call_hooks('import_foreign_channel_data',$data);
if($data['handled'])
if (!array_key_exists('compatibility', $data)) {
call_hooks('import_foreign_channel_data', $data);
if ($data['handled'])
return;
}
@@ -133,47 +133,47 @@ class Import extends \Zotlabs\Web\Controller {
// prevent incompatible osada or zap data from horking your database
if(array_path_exists('compatibility/codebase',$data)) {
if (array_path_exists('compatibility/codebase', $data)) {
notice('Data export format is not compatible with this software');
return;
}
if(version_compare($data['compatibility']['version'], '4.7.3', '<=')) {
if (version_compare($data['compatibility']['version'], '4.7.3', '<=')) {
// zot6 transition: cloning is not compatible with older versions
notice('Data export format is not compatible with this software (not a zot6 channel)');
return;
}
if($moving)
if ($moving)
$seize = 1;
// import channel
$relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null);
$relocate = ((array_key_exists('relocate', $data)) ? $data['relocate'] : null);
if(array_key_exists('channel',$data)) {
if (array_key_exists('channel', $data)) {
$max_identities = account_service_class_fetch($account_id,'total_identities');
$max_identities = account_service_class_fetch($account_id, 'total_identities');
if($max_identities !== false) {
$r = q("select channel_id from channel where channel_account_id = %d",
if ($max_identities !== false) {
$r = q("select channel_id from channel where channel_account_id = %d and channel_removed = 0",
intval($account_id)
);
if($r && count($r) > $max_identities) {
notice( sprintf( t('Your service plan only allows %d channels.'), $max_identities) . EOL);
if ($r && count($r) > $max_identities) {
notice(sprintf(t('Your service plan only allows %d channels.'), $max_identities) . EOL);
return;
}
}
if($newname) {
$x = false;
if ($newname) {
$x = false;
if(get_config('system','unicode_usernames')) {
$x = punify(mb_strtolower($newname));
}
if (get_config('system', 'unicode_usernames')) {
$x = punify(mb_strtolower($newname));
}
if((! $x) || strlen($x) > 64) {
$x = strtolower(\URLify::transliterate($newname));
if ((!$x) || strlen($x) > 64) {
$x = strtolower(URLify::transliterate($newname));
}
$newname = $x;
}
@@ -182,65 +182,38 @@ class Import extends \Zotlabs\Web\Controller {
}
else {
$moving = false;
$channel = \App::get_channel();
$channel = App::get_channel();
}
if(! $channel) {
logger('Channel not found. ', print_r($channel,true));
notice( t('No channel. Import failed.') . EOL);
if (!$channel) {
logger('Channel not found. ', print_r($channel, true));
notice(t('No channel. Import failed.') . EOL);
return;
}
if(is_array($data['config'])) {
import_config($channel,$data['config']);
if (is_array($data['config'])) {
import_config($channel, $data['config']);
}
logger('import step 2');
if(array_key_exists('channel',$data)) {
if($data['photo']) {
if (array_key_exists('channel', $data)) {
if ($data['photo']) {
require_once('include/photo/photo_driver.php');
import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],$account_id,$channel['channel_id']);
import_channel_photo(base64url_decode($data['photo']['data']), $data['photo']['type'], $account_id, $channel['channel_id']);
}
if(is_array($data['profile']))
import_profiles($channel,$data['profile']);
if (is_array($data['profile']))
import_profiles($channel, $data['profile']);
}
logger('import step 3');
// create new hubloc for the new channel at this site
if(array_key_exists('channel',$data)) {
if($channel['channel_portable_id']) {
$r = hubloc_store_lowlevel(
[
'hubloc_guid' => $channel['channel_guid'],
'hubloc_guid_sig' => $channel['channel_guid_sig'],
'hubloc_hash' => $channel['channel_portable_id'],
'hubloc_addr' => channel_reddress($channel),
'hubloc_network' => 'zot',
'hubloc_primary' => (($seize) ? 1 : 0),
'hubloc_url' => z_root(),
'hubloc_url_sig' => base64url_encode(Crypto::sign(z_root(),$channel['channel_prvkey'])),
'hubloc_host' => \App::get_hostname(),
'hubloc_callback' => z_root() . '/post',
'hubloc_sitekey' => get_config('system','pubkey'),
'hubloc_updated' => datetime_convert(),
'hubloc_id_url' => channel_url($channel)
]
);
if (array_key_exists('channel', $data)) {
// reset the original primary hubloc if it is being seized
if($seize) {
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
dbesc($channel['channel_portable_id']),
dbesc(z_root())
);
}
}
// create a new zot6 hubloc if we have got a channel_portable_id
// create a new zot6 hubloc
$r = hubloc_store_lowlevel(
[
@@ -251,18 +224,18 @@ class Import extends \Zotlabs\Web\Controller {
'hubloc_network' => 'zot6',
'hubloc_primary' => (($seize) ? 1 : 0),
'hubloc_url' => z_root(),
'hubloc_url_sig' => 'sha256.' . base64url_encode(Crypto::sign(z_root(),$channel['channel_prvkey'])),
'hubloc_host' => \App::get_hostname(),
'hubloc_url_sig' => Libzot::sign(z_root(), $channel['channel_prvkey']),
'hubloc_host' => App::get_hostname(),
'hubloc_callback' => z_root() . '/zot',
'hubloc_sitekey' => get_config('system','pubkey'),
'hubloc_sitekey' => get_config('system', 'pubkey'),
'hubloc_updated' => datetime_convert(),
'hubloc_id_url' => channel_url($channel),
'hubloc_site_id' => Libzot::make_xchan_hash(z_root(),get_config('system','pubkey'))
'hubloc_site_id' => Libzot::make_xchan_hash(z_root(), get_config('system', 'pubkey'))
]
);
// reset the original primary hubloc if it is being seized
if($seize) {
if ($seize) {
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
dbesc($channel['channel_hash']),
dbesc(z_root())
@@ -273,57 +246,33 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 4');
// import xchans and contact photos
if(array_key_exists('channel',$data) && $seize) {
if (array_key_exists('channel', $data) && $seize) {
// replace any existing xchan we may have on this site if we're seizing control
$r = q("delete from xchan where ( xchan_hash = '%s' or xchan_hash = '%s' ) ",
dbesc($channel['channel_hash']),
dbesc($channel['channel_portable_id'])
$r = q("delete from xchan where xchan_hash = '%s'",
dbesc($channel['channel_hash'])
);
if($channel['channel_portable_id']) {
$r = xchan_store_lowlevel(
[
'xchan_hash' => $channel['channel_portable_id'],
'xchan_guid' => $channel['channel_guid'],
'xchan_guid_sig' => $channel['channel_guid_sig'],
'xchan_pubkey' => $channel['channel_pubkey'],
'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'],
'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'],
'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'],
'xchan_addr' => channel_reddress($channel),
'xchan_url' => z_root() . '/channel/' . $channel['channel_address'],
'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
'xchan_follow' => z_root() . '/follow?f=&url=%s',
'xchan_name' => $channel['channel_name'],
'xchan_network' => 'zot',
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert()
]
);
}
$r = xchan_store_lowlevel(
[
'xchan_hash' => $channel['channel_hash'],
'xchan_guid' => $channel['channel_guid'],
'xchan_guid_sig' => $channel['channel_guid_sig'],
'xchan_pubkey' => $channel['channel_pubkey'],
'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'],
'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'],
'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'],
'xchan_addr' => channel_reddress($channel),
'xchan_url' => z_root() . '/channel/' . $channel['channel_address'],
'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
'xchan_follow' => z_root() . '/follow?f=&url=%s',
'xchan_name' => $channel['channel_name'],
'xchan_network' => 'zot6',
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert()
'xchan_hash' => $channel['channel_hash'],
'xchan_guid' => $channel['channel_guid'],
'xchan_guid_sig' => $channel['channel_guid_sig'],
'xchan_pubkey' => $channel['channel_pubkey'],
'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'],
'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'],
'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'],
'xchan_addr' => channel_reddress($channel),
'xchan_url' => z_root() . '/channel/' . $channel['channel_address'],
'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
'xchan_follow' => z_root() . '/follow?f=&url=%s',
'xchan_name' => $channel['channel_name'],
'xchan_network' => 'zot6',
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert()
]
);
@@ -333,26 +282,18 @@ class Import extends \Zotlabs\Web\Controller {
// import xchans
$xchans = $data['xchan'];
if($xchans) {
foreach($xchans as $xchan) {
if ($xchans) {
foreach ($xchans as $xchan) {
if($xchan['xchan_network'] === 'zot') {
$hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
if($hash !== $xchan['xchan_hash']) {
logger('forged xchan: ' . print_r($xchan,true));
if ($xchan['xchan_network'] === 'zot6') {
$zhash = Libzot::make_xchan_hash($xchan['xchan_guid'], $xchan['xchan_pubkey']);
if ($zhash !== $xchan['xchan_hash']) {
logger('forged xchan: ' . print_r($xchan, true));
continue;
}
}
if($xchan['xchan_network'] === 'zot6') {
$zhash = Libzot::make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_pubkey']);
if($zhash !== $xchan['xchan_hash']) {
logger('forged xchan: ' . print_r($xchan,true));
continue;
}
}
if(! array_key_exists('xchan_hidden',$xchan)) {
if (!array_key_exists('xchan_hidden', $xchan)) {
$xchan['xchan_hidden'] = (($xchan['xchan_flags'] & 0x0001) ? 1 : 0);
$xchan['xchan_orphan'] = (($xchan['xchan_flags'] & 0x0002) ? 1 : 0);
$xchan['xchan_censored'] = (($xchan['xchan_flags'] & 0x0004) ? 1 : 0);
@@ -365,14 +306,14 @@ class Import extends \Zotlabs\Web\Controller {
$r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
dbesc($xchan['xchan_hash'])
);
if($r)
if ($r)
continue;
create_table_from_array('xchan',$xchan);
create_table_from_array('xchan', $xchan);
require_once('include/photo/photo_driver.php');
if($xchan['xchan_hash'] === $channel['channel_hash']) {
if ($xchan['xchan_hash'] === $channel['channel_hash']) {
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s'",
dbesc(z_root() . '/photo/profile/l/' . $channel['channel_id']),
dbesc(z_root() . '/photo/profile/m/' . $channel['channel_id']),
@@ -381,13 +322,13 @@ class Import extends \Zotlabs\Web\Controller {
);
}
else {
$photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']);
if($photos[4])
$photos = import_xchan_photo($xchan['xchan_photo_l'], $xchan['xchan_hash']);
if ($photos[4])
$photodate = NULL_DATE;
else
$photodate = $xchan['xchan_photo_date'];
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
@@ -404,22 +345,22 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 7');
// this must happen after xchans got imported!
if(is_array($data['hubloc'])) {
import_hublocs($channel,$data['hubloc'],$seize,$moving);
if (is_array($data['hubloc'])) {
import_hublocs($channel, $data['hubloc'], $seize, $moving);
}
$friends = 0;
$feeds = 0;
$feeds = 0;
// import contacts
$abooks = $data['abook'];
if($abooks) {
foreach($abooks as $abook) {
if ($abooks) {
foreach ($abooks as $abook) {
$abook_copy = $abook;
$abconfig = null;
if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
if (array_key_exists('abconfig', $abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
$abconfig = $abook['abconfig'];
unset($abook['abook_id']);
@@ -432,33 +373,33 @@ class Import extends \Zotlabs\Web\Controller {
$abook['abook_account'] = $account_id;
$abook['abook_channel'] = $channel['channel_id'];
if(! array_key_exists('abook_blocked',$abook)) {
$abook['abook_blocked'] = (($abook['abook_flags'] & 0x0001 ) ? 1 : 0);
$abook['abook_ignored'] = (($abook['abook_flags'] & 0x0002 ) ? 1 : 0);
$abook['abook_hidden'] = (($abook['abook_flags'] & 0x0004 ) ? 1 : 0);
$abook['abook_archived'] = (($abook['abook_flags'] & 0x0008 ) ? 1 : 0);
$abook['abook_pending'] = (($abook['abook_flags'] & 0x0010 ) ? 1 : 0);
$abook['abook_unconnected'] = (($abook['abook_flags'] & 0x0020 ) ? 1 : 0);
$abook['abook_self'] = (($abook['abook_flags'] & 0x0080 ) ? 1 : 0);
$abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0);
if (!array_key_exists('abook_blocked', $abook)) {
$abook['abook_blocked'] = (($abook['abook_flags'] & 0x0001) ? 1 : 0);
$abook['abook_ignored'] = (($abook['abook_flags'] & 0x0002) ? 1 : 0);
$abook['abook_hidden'] = (($abook['abook_flags'] & 0x0004) ? 1 : 0);
$abook['abook_archived'] = (($abook['abook_flags'] & 0x0008) ? 1 : 0);
$abook['abook_pending'] = (($abook['abook_flags'] & 0x0010) ? 1 : 0);
$abook['abook_unconnected'] = (($abook['abook_flags'] & 0x0020) ? 1 : 0);
$abook['abook_self'] = (($abook['abook_flags'] & 0x0080) ? 1 : 0);
$abook['abook_feed'] = (($abook['abook_flags'] & 0x0100) ? 1 : 0);
}
if(array_key_exists('abook_instance',$abook) && $abook['abook_instance'] && strpos($abook['abook_instance'],z_root()) === false) {
if (array_key_exists('abook_instance', $abook) && $abook['abook_instance'] && strpos($abook['abook_instance'], z_root()) === false) {
$abook['abook_not_here'] = 1;
}
if($abook['abook_self']) {
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) {
if ($abook['abook_self']) {
$role = get_pconfig($channel['channel_id'], 'system', 'permissions_role');
if (($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) {
q("update xchan set xchan_pubforum = 1 where xchan_hash = '%s' ",
dbesc($abook['abook_xchan'])
);
}
}
else {
if($max_friends !== false && $friends > $max_friends)
if ($max_friends !== false && $friends > $max_friends)
continue;
if($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds))
if ($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds))
continue;
}
@@ -466,9 +407,9 @@ class Import extends \Zotlabs\Web\Controller {
dbesc($abook['abook_xchan']),
intval($channel['channel_id'])
);
if($r) {
foreach($abook as $k => $v) {
$r = q("UPDATE abook SET " . TQUOT . "%s" . TQUOT . " = '%s' WHERE abook_xchan = '%s' AND abook_channel = %d",
if ($r) {
foreach ($abook as $k => $v) {
q("UPDATE abook SET " . TQUOT . "%s" . TQUOT . " = '%s' WHERE abook_xchan = '%s' AND abook_channel = %d",
dbesc($k),
dbesc($v),
dbesc($abook['abook_xchan']),
@@ -479,17 +420,17 @@ class Import extends \Zotlabs\Web\Controller {
else {
abook_store_lowlevel($abook);
$friends ++;
if(intval($abook['abook_feed']))
$feeds ++;
$friends++;
if (intval($abook['abook_feed']))
$feeds++;
}
translate_abook_perms_inbound($channel,$abook_copy);
translate_abook_perms_inbound($channel, $abook_copy);
if($abconfig) {
if ($abconfig) {
/// @FIXME does not handle sync of del_abconfig
foreach($abconfig as $abc) {
set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
foreach ($abconfig as $abc) {
set_abconfig($channel['channel_id'], $abc['xchan'], $abc['cat'], $abc['k'], $abc['v']);
}
}
}
@@ -497,13 +438,14 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 8');
}
// import groups
$groups = $data['group'];
if($groups) {
$saved = array();
foreach($groups as $group) {
$saved[$group['hash']] = array('old' => $group['id']);
if(array_key_exists('name', $group)) {
if ($groups) {
$saved = [];
foreach ($groups as $group) {
$saved[$group['hash']] = ['old' => $group['id']];
if (array_key_exists('name', $group)) {
$group['gname'] = $group['name'];
unset($group['name']);
}
@@ -515,8 +457,8 @@ class Import extends \Zotlabs\Web\Controller {
$r = q("select * from pgrp where uid = %d",
intval($channel['channel_id'])
);
if($r) {
foreach($r as $rr) {
if ($r) {
foreach ($r as $rr) {
$saved[$rr['hash']]['new'] = $rr['id'];
}
}
@@ -524,12 +466,12 @@ class Import extends \Zotlabs\Web\Controller {
// import group members
$group_members = $data['group_member'];
if($group_members) {
foreach($group_members as $group_member) {
if ($group_members) {
foreach ($group_members as $group_member) {
unset($group_member['id']);
$group_member['uid'] = $channel['channel_id'];
foreach($saved as $x) {
if($x['old'] == $group_member['gid'])
foreach ($saved as $x) {
if ($x['old'] == $group_member['gid'])
$group_member['gid'] = $x['new'];
}
create_table_from_array('pgrp_member', $group_member);
@@ -538,65 +480,85 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 9');
if(is_array($data['obj']))
import_objs($channel,$data['obj']);
if(is_array($data['likes']))
import_likes($channel,$data['likes']);
if (is_array($data['obj']))
import_objs($channel, $data['obj']);
if(is_array($data['app']))
import_apps($channel,$data['app']);
if (is_array($data['likes']))
import_likes($channel, $data['likes']);
if(is_array($data['sysapp']))
import_sysapps($channel,$data['sysapp']);
if (is_array($data['app']))
import_apps($channel, $data['app']);
if(is_array($data['chatroom']))
import_chatrooms($channel,$data['chatroom']);
if (is_array($data['sysapp']))
import_sysapps($channel, $data['sysapp']);
if(is_array($data['conv']))
import_conv($channel,$data['conv']);
if (is_array($data['chatroom']))
import_chatrooms($channel, $data['chatroom']);
if(is_array($data['mail']))
import_mail($channel,$data['mail']);
if (is_array($data['event']))
import_events($channel, $data['event']);
if(is_array($data['event']))
import_events($channel,$data['event']);
if (is_array($data['event_item']))
import_items($channel, $data['event_item'], false, $relocate);
if(is_array($data['event_item']))
import_items($channel,$data['event_item'],false,$relocate);
if (is_array($data['menu']))
import_menus($channel, $data['menu']);
if(is_array($data['menu']))
import_menus($channel,$data['menu']);
if (is_array($data['wiki']))
import_items($channel, $data['wiki'], false, $relocate);
if(is_array($data['wiki']))
import_items($channel,$data['wiki'],false,$relocate);
if (is_array($data['webpages']))
import_items($channel, $data['webpages'], false, $relocate);
if(is_array($data['webpages']))
import_items($channel,$data['webpages'],false,$relocate);
$addon = ['channel' => $channel, 'data' => $data];
call_hooks('import_channel', $addon);
$addon = array('channel' => $channel,'data' => $data);
call_hooks('import_channel',$addon);
if ($import_posts && array_key_exists('item', $data) && $data['item']) {
import_items($channel, $data['item'], false, $relocate);
}
$saved_notification_flags = notifications_off($channel['channel_id']);
if($import_posts && array_key_exists('item',$data) && $data['item'])
import_items($channel,$data['item'],false,$relocate);
notifications_on($channel['channel_id'],$saved_notification_flags);
if(array_key_exists('item_id',$data) && $data['item_id'])
import_item_ids($channel,$data['item_id']);
// Immediately notify old server about the new clone
Master::Summon(['Notifier', 'refresh_all', $channel['channel_id']]);
// This will indirectly perform a refresh_all *and* update the directory
Master::Summon(['Directory', $channel['channel_id']]);
\Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id']));
$cf_api_compat = true;
if ($api_path && $import_posts) { // we are importing from a server and not a file
if (version_compare($data['compatibility']['version'], '6.3.4', '>=')) {
notice( t('Import completed.') . EOL);
$m = parse_url($api_path);
$hz_server = $m['scheme'] . '://' . $m['host'];
$since = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), '0001-01-01 00:00');
$until = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), 'now + 1 day');
$poll_interval = get_config('system', 'poll_interval', 3);
$page = 0;
Master::Summon(['Content_importer', sprintf('%d', $page), $since, $until, $channel['channel_address'], urlencode($hz_server)]);
Master::Summon(['File_importer', sprintf('%d', $page), $channel['channel_address'], urlencode($hz_server)]);
}
else {
$cf_api_compat = false;
}
}
change_channel($channel['channel_id']);
goaway(z_root() . '/network' );
if ($api_path && $import_posts && $cf_api_compat) {
goaway(z_root() . '/import_progress');
}
if (!$cf_api_compat) {
notice(t('Automatic content and files import was not possible due to API version incompatiblity. Please import content and files manually!') . EOL);
}
goaway(z_root());
}
/**
@@ -604,7 +566,7 @@ class Import extends \Zotlabs\Web\Controller {
*/
function post() {
$account_id = get_account_id();
if(! $account_id)
if (!$account_id)
return;
check_form_security_token_redirectOnErr('/import', 'channel_import');
@@ -619,33 +581,35 @@ class Import extends \Zotlabs\Web\Controller {
*/
function get() {
if(! get_account_id()) {
notice( t('You must be logged in to use this feature.') . EOL);
if (!get_account_id()) {
notice(t('You must be logged in to use this feature.') . EOL);
return '';
}
$o = replace_macros(get_markup_template('channel_import.tpl'),array(
'$title' => t('Import Channel'),
'$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'),
'$label_filename' => t('File to Upload'),
'$choice' => t('Or provide the old server/hub details'),
nav_set_selected('Channel Import');
'$old_address' => [ 'old_address', t('Your old identity address (xyz@example.com)'), '', ''],
'$email' => [ 'email', t('Your old login email address'), '', '' ],
'$password' => [ 'password', t('Your old login password'), '', '' ],
'$import_posts' => [ 'import_posts', t('Import a few months of posts if possible (limited by available memory'), false, '', [ t('No'), t('Yes') ]],
$o = replace_macros(get_markup_template('channel_import.tpl'), [
'$title' => t('Channel Import'),
'$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'),
'$label_filename' => t('File to Upload'),
'$choice' => t('Or provide the old server/hub details'),
'$old_address' => ['old_address', t('Your old identity address (xyz@example.com)'), '', ''],
'$email' => ['email', t('Your old login email address'), '', ''],
'$password' => ['password', t('Your old login password'), '', ''],
'$import_posts' => ['import_posts', t('Import your items and files (limited by available memory)'), false, '', [t('No'), t('Yes')]],
'$common' => t('For either option, please choose whether to make this hub your new primary address, or whether your old location should continue this role. You will be able to post from either location, but only one can be marked as the primary location for files, photos, and media.'),
'$make_primary' => [ 'make_primary', t('Make this hub my primary location'), false, '', [ t('No'), t('Yes') ] ],
'$moving' => [ 'moving', t('Move this channel (disable all previous locations)'), false, '', [ t('No'), t('Yes') ] ],
'$newname' => [ 'newname', t('Use this channel nickname instead of the one provided'), '', t('Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site.')],
'$make_primary' => ['make_primary', t('Make this hub my primary location'), false, '', [t('No'), t('Yes')]],
'$moving' => ['moving', t('Move this channel (disable all previous locations)'), false, '', [t('No'), t('Yes')]],
'$newname' => ['newname', t('Use this channel nickname instead of the one provided'), '', t('Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site.')],
'$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'),
'$form_security_token' => get_form_security_token('channel_import'),
'$submit' => t('Submit')
));
'$submit' => t('Submit')
]);
return $o;
}

View File

@@ -1,6 +1,11 @@
<?php
namespace Zotlabs\Module;
use App;
use ZipArchive;
use Zotlabs\Web\Controller;
require_once('include/import.php');
/**
@@ -8,104 +13,95 @@ require_once('include/import.php');
*
* Import existing posts and content from an export file.
*/
class Import_items extends \Zotlabs\Web\Controller {
class Import_items extends Controller {
function post() {
if(! local_channel())
if (!local_channel())
return;
check_form_security_token_redirectOnErr('/import_items', 'import_items');
$data = null;
$data = null;
$src = $_FILES['filename']['tmp_name'];
$filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type'];
if($src) {
// This is OS specific and could also fail if your tmpdir isn't very large
// mostly used for Diaspora which exports gzipped files.
$channel = App::get_channel();
if(strpos($filename,'.gz')){
@rename($src,$src . '.gz');
@system('gunzip ' . escapeshellarg($src . '.gz'));
}
if ($src) {
if($filesize) {
$data = @file_get_contents($src);
}
unlink($src);
}
if ($filetype === 'application/zip') {
$zip = new ZipArchive;
if(! $src) {
$r = $zip->open($src);
if ($r === true) {
for ($i = 0; $i < $zip->count(); $i++) {
$data = $zip->getFromIndex($i);
self::import($channel, $data);
}
$zip->close();
unlink($src);
return;
}
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
if(! $old_address) {
logger('Nothing to import.');
notice( t('Nothing to import.') . EOL);
notice(t('Not a zip file or zip file corrupted.') . EOL);
unlink($src);
return;
}
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
// This is OS specific and could also fail if your tmpdir isn't very large
// mostly used for Diaspora which exports gzipped files.
$year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : '');
//if(strpos($filename,'.gz')){
//@rename($src,$src . '.gz');
//@system('gunzip ' . escapeshellarg($src . '.gz'));
//}
$channelname = substr($old_address,0,strpos($old_address,'@'));
$servername = substr($old_address,strpos($old_address,'@')+1);
$scheme = 'https://';
$api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year);
$binary = false;
$redirects = 0;
$opts = array('http_auth' => $email . ':' . $password);
$url = $scheme . $servername . $api_path;
$ret = z_fetch_url($url, $binary, $redirects, $opts);
if(! $ret['success'])
$ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
if($ret['success'])
$data = $ret['body'];
else
notice( t('Unable to download data from old server') . EOL);
}
if(! $data) {
logger('Empty file.');
notice( t('Imported file is empty.') . EOL);
return;
}
$data = json_decode($data, true);
//logger('import: data: ' . print_r($data,true));
//print_r($data);
if(! is_array($data))
return;
if(array_key_exists('compatibility',$data) && array_key_exists('database',$data['compatibility'])) {
$v1 = substr($data['compatibility']['database'],-4);
$v2 = substr(DB_UPDATE_VERSION,-4);
if($v2 > $v1) {
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
notice($t . EOL);
if ($filesize) {
$data = @file_get_contents($src);
self::import($channel, $data);
}
unlink($src);
return;
}
/*
if(! $src) {
$channel = \App::get_channel();
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
if(array_key_exists('item',$data) && $data['item']) {
import_items($channel,$data['item'],false,((array_key_exists('relocate',$data)) ? $data['relocate'] : null));
}
if(! $old_address) {
logger('Nothing to import.');
notice( t('Nothing to import.') . EOL);
return;
}
if(array_key_exists('item_id',$data) && $data['item_id']) {
import_item_ids($channel,$data['item_id']);
}
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
$year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : '');
$channelname = substr($old_address,0,strpos($old_address,'@'));
$servername = substr($old_address,strpos($old_address,'@')+1);
$scheme = 'https://';
$api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year);
$binary = false;
$redirects = 0;
$opts = array('http_auth' => $email . ':' . $password);
$url = $scheme . $servername . $api_path;
$ret = z_fetch_url($url, $binary, $redirects, $opts);
if(! $ret['success'])
$ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
if($ret['success'])
$data = $ret['body'];
else
notice( t('Unable to download data from old server') . EOL);
}
*/
info( t('Import completed') . EOL);
}
@@ -116,20 +112,85 @@ class Import_items extends \Zotlabs\Web\Controller {
*/
function get() {
if(! local_channel()) {
notice( t('Permission denied') . EOL);
if (!local_channel()) {
notice(t('Permission denied') . EOL);
return login();
}
$o = replace_macros(get_markup_template('item_import.tpl'), array(
'$title' => t('Import Items'),
'$desc' => t('Use this form to import existing posts and content from an export file.'),
'$label_filename' => t('File to Upload'),
$o = replace_macros(get_markup_template('item_import.tpl'), [
'$title' => t('Import Items'),
'$desc' => t('Use this form to import existing posts and content from an export file.'),
'$label_filename' => t('File to Upload'),
'$form_security_token' => get_form_security_token('import_items'),
'$submit' => t('Submit')
));
'$submit' => t('Submit')
]);
return $o;
}
public static function import($channel, $data) {
if (!$data) {
logger('Empty file.');
notice(t('Imported file is empty.') . EOL);
return;
}
$data = json_decode($data, true);
//logger('import: data: ' . print_r($data,true));
//print_r($data);
if (!is_array($data)) {
return;
}
//if (array_key_exists('compatibility', $data) && array_key_exists('database', $data['compatibility'])) {
//$v1 = substr($data['compatibility']['database'], -4);
//$v2 = substr(DB_UPDATE_VERSION, -4);
//if ($v2 > $v1) {
//$t = sprintf(t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1);
//notice($t . EOL);
//}
//}
if (array_key_exists('item', $data) && is_array($data['item'])) {
import_items($channel, $data['item'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null));
info(t('Content import completed') . EOL);
}
if (array_key_exists('chatroom', $data) && is_array($data['chatroom'])) {
import_chatrooms($channel, $data['chatroom']);
info(t('Chatroom import completed') . EOL);
}
if (array_key_exists('event', $data) && is_array($data['event'])) {
import_events($channel, $data['event']);
info(t('Channel calendar import 1/2 completed') . EOL);
}
if (array_key_exists('event_item', $data) && is_array($data['event_item'])) {
import_items($channel, $data['event_item'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null));
info(t('Channel calendar import 2/2 completed') . EOL);
}
if (array_key_exists('menu', $data) && is_array($data['menu'])) {
import_menus($channel, $data['menu']);
info(t('Menu import completed') . EOL);
}
if (array_key_exists('wiki', $data) && is_array($data['wiki'])) {
import_items($channel, $data['wiki'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null));
info(t('Wiki import completed') . EOL);
}
if (array_key_exists('webpages', $data) && is_array($data['webpages'])) {
import_items($channel, $data['webpages'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null));
info(t('Webpages import completed') . EOL);
}
}
}

View File

@@ -0,0 +1,122 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Lib\PConfig;
use Zotlabs\Daemon\Master;
class Import_progress extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
}
function get() {
if(! local_channel()) {
return;
}
nav_set_selected('Channel Import');
// items
$c = PConfig::Get(local_channel(), 'import', 'content_progress');
if ($c) {
$total_cpages = floor(intval($c['items_total']) / intval($c['items_page']));
if(!$total_cpages) {
$total_cpages = 1; // because of floor
}
$cpage = $c['last_page'] + 1; // because page count start at 0
$cprogress = intval(floor((intval($cpage) * 100) / $total_cpages));
$ccompleted_str = t('Item sync completed!');
if(argv(1) === 'resume_itemsync' && $cprogress < 100) {
Master::Summon($c['next_cmd']);
goaway('/import_progress');
}
}
else {
$cprogress = 'waiting to start...';
if (PConfig::Get(local_channel(), 'import', 'content_completed')) {
// There was nothing todo. Fake 100% and mention that there were no files found
$cprogress = 100;
}
$ccompleted_str = t('Item sync completed but no items were found!');
if(argv(1) === 'resume_itemsync') {
Master::Summon(["Content_importer","0","0001-01-01 00:00:00","2021-10-02 19:49:14","ct5","https%3A%2F%2Fhub.somaton.com"]);
goaway('/import_progress');
}
}
$cprogress_str = ((intval($cprogress)) ? $cprogress . '%' : $cprogress);
// files
$f = PConfig::Get(local_channel(), 'import', 'files_progress');
if ($f) {
$total_fpages = floor(intval($f['files_total']) / intval($f['files_page']));
if(!$total_fpages) {
$total_fpages = 1;
}
$fpage = $f['last_page'] + 1;
$fprogress = intval(floor((intval($fpage) * 100) / $total_fpages));
$fcompleted_str = t('File sync completed!');
if(argv(1) === 'resume_filesync' && $fprogress < 100) {
Master::Summon($f['next_cmd']);
goaway('/import_progress');
}
}
else {
$fprogress = 'waiting to start...';
if (PConfig::Get(local_channel(), 'import', 'files_completed')) {
// There was nothing todo. Fake 100% and mention that there were no files found
$fprogress = 100;
}
$fcompleted_str = t('File sync completed but no files were found!');
}
$fprogress_str = ((intval($fprogress)) ? $fprogress . '%' : $fprogress);
if(is_ajax()) {
$ret = [
'cprogress' => $cprogress,
'fprogress' => $fprogress
];
json_return_and_die($ret);
}
$o = replace_macros(get_markup_template("import_progress.tpl"), [
'$chtitle_str' => t('Channel clone status'),
'$ctitle_str' => t('Item sync status'),
'$ftitle_str' => t('File sync status'),
'$cprogress_str' => $cprogress_str,
'$cprogress' => intval($cprogress),
'$fprogress_str' => $fprogress_str,
'$fprogress' => intval($fprogress),
'$fcompleted_str' => $fcompleted_str,
'$ccompleted_str' => $ccompleted_str,
'$chcompleted_str' => t('Channel cloning completed!'),
'$resume_str' => t('Resume'),
'$resume_helper_str' => t('Only resume if sync stalled!')
]);
return $o;
}
}

View File

@@ -129,11 +129,11 @@ class Invite extends Controller {
if(! $recip) continue;
// see if we have an email address who@domain.tld
if (!preg_match('/^.{2,64}\@[a-z0-9.-]{4,32}\.[a-z]{2,12}$/', $recip)) {
$feedbk .= 'ZAI0203E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a valid email address'), $recip) . $eol;
$ko++;
continue;
}
//if (!preg_match('/^.{2,64}\@[a-z0-9.-]{2,32}\.[a-z]{2,12}$/', $recip)) {
//$feedbk .= 'ZAI0203E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a valid email address'), $recip) . $eol;
//$ko++;
//continue;
//}
if(! validate_email($recip)) {
$feedbk .= 'ZAI0204E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a real email address'), $recip) . $eol;
$ko++;
@@ -225,7 +225,7 @@ class Invite extends Controller {
'$projectname' => t('$Projectname'),
'$invite_code' => $invite_code,
'$invite_where' => z_root() . '/register',
'$invite_whereami' => str_replace('@', '@+', $reonar['whereami']),
'$invite_whereami' => $reonar['whereami'],
'$invite_whoami' => z_root() . '/channel/' . $reonar['whoami'],
'$invite_anywhere' => z_root() . '/pubsites'
)
@@ -306,9 +306,8 @@ class Invite extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Invite')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = 'ZAI0102E,' . t('Invite App') . ' (' . t('Not Installed') . ')' . EOL;
return $o;
$papp = Apps::get_papp('Invite');
return Apps::app_render($papp, 'module');
}
if (! (get_config('system','invitation_also') || get_config('system','invitation_only')) ) {
@@ -423,8 +422,6 @@ class Invite extends Controller {
// let take one descriptive for template (as said is never used)
$invite_code = 'INVITATE2020';
// what languages we use now
$lccmy = ((isset(App::$config['system']['language'])) ? App::$config['system']['language'] : 'en');
// and all the localized templates belonging to invite
$tpls = glob('view/*/invite.*.tpl');
@@ -445,6 +442,9 @@ class Invite extends Controller {
$langs = array_keys($tpla);
asort($langs);
// Use the current language if we have a template for it. Otherwise fall back to 'en'.
$lccmy = ((in_array(App::$language, $langs)) ? App::$language : 'en');
$tplx = array_unique($tplx);
asort($tplx);

File diff suppressed because it is too large Load Diff

View File

@@ -7,16 +7,60 @@ use Zotlabs\Web\Controller;
class Lang extends Controller {
const MYP = 'ZIN';
const VERSION = '2.0.0';
function post() {
$re = [];
$isajax = is_ajax();
$eol = $isajax ? "\n" : EOL;
if (! Apps::system_app_installed(local_channel(), 'Language')) {
$re['msg'] = 'ZIN0202E, ' . t('Language App') . ' (' . t('Not Installed') . ')' ;
notice( $re['msg'] . EOL);
if ($isajax) {
echo json_encode( $re );
killme();
exit;
} else {
return;
}
}
$lc = x($_POST['zinlc']) && preg_match('/^\?\?|[a-z]{2,2}[x_\-]{0,1}[a-zA-Z]{0,2}$/', $_POST['zinlc'])
? $_POST['zinlc'] : '';
$lcs= x($_POST['zinlcs']) && preg_match('/^[a-z,_\-]{0,191}$/', $_POST['zinlcs'])
? $_POST['zinlcs'] : '';
if ($isajax) {
if ($lc == '??') {
$re['lc'] = get_best_language();
$re['lcs'] = language_list();
} else {
$re['lc'] = $lc;
$re['alc'] = App::$language;
$re['slc'] = $_SESSION['language'];
$_SESSION['language'] = $lc;
App::$language = $lc;
load_translation_table($lc, true);
}
echo json_encode( $re );
killme();
exit;
}
}
function get() {
if(local_channel()) {
if(! Apps::system_app_installed(local_channel(), 'Language')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Language App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Change UI language');
return $o;
//Do not display any associated widgets at this point
App::$pdl = '';
$papp = Apps::get_papp('Language');
return Apps::app_render($papp, 'module');
}
}
@@ -24,5 +68,5 @@ class Lang extends Controller {
return lang_selector();
}
}

View File

@@ -5,37 +5,40 @@ namespace Zotlabs\Module;
class Linkinfo extends \Zotlabs\Web\Controller {
function get() {
logger('linkinfo: ' . print_r($_REQUEST,true));
$text = null;
$str_tags = '';
$process_oembed = true;
$process_oembed = true;
$br = "\n";
if(x($_GET,'binurl'))
$url = trim(hex2bin($_GET['binurl']));
else
$url = trim($_GET['url']);
if(substr($url,0,1) === '!') {
$process_oembed = false;
$url = substr($url,1);
}
$url = strip_zids($url);
if((substr($url,0,1) != '/') && (substr($url,0,4) != 'http'))
$url = 'http://' . $url;
$x = parse_url($url);
if ($x)
$url = str_replace($x['host'], punify($x['host']), $url);
if($_GET['title'])
$title = strip_tags(trim($_GET['title']));
if($_GET['description'])
$text = strip_tags(trim($_GET['description']));
if($_GET['tags']) {
$arr_tags = str_getcsv($_GET['tags']);
if(count($arr_tags)) {
@@ -43,23 +46,25 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$str_tags = $br . implode(' ',$arr_tags) . $br;
}
}
logger('linkinfo: ' . $url);
// Replace plink URL with 'share' tag if possible
preg_match("/(mid=b64\.|display\/|posts\/)([\w\-]+)(&.+)?$/", $url, $mid);
if (!empty($mid) && $mid[1] == 'mid=b64.')
$mid[2] = base64_decode($mid[2]);
// Replace plink URL with 'share' tag if possible
preg_match("/(mid=b64\.|display\/|posts\/)([\w\-]+)(&.+)?$/", $url, $mid);
$r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
dbesc((empty($mid) ? $url : $mid[2])),
intval(local_channel())
);
if ($r) {
echo "[share=" . $r[0]['id'] . "][/share]";
killme();
}
if (!empty($mid)) {
$mid[2] = unpack_link_id($mid[2]);
}
$r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
dbesc((empty($mid) ? $url : $mid[2])),
intval(local_channel())
);
if ($r) {
echo "[share=" . $r[0]['id'] . "][/share]";
killme();
}
$result = z_fetch_url($url,false,0,array('novalidate' => true, 'nobody' => true));
if($result['success']) {
@@ -108,13 +113,13 @@ class Linkinfo extends \Zotlabs\Web\Controller {
}
}
}
$template = $br . '#^[url=%s]%s[/url]%s' . $br;
$arr = array('url' => $url, 'text' => '');
call_hooks('parse_link', $arr);
if(strlen($arr['text'])) {
echo $arr['text'];
killme();
@@ -127,28 +132,28 @@ class Linkinfo extends \Zotlabs\Web\Controller {
killme();
}
}
if($url && $title && $text) {
$text = $br . '[quote]' . trim($text) . '[/quote]' . $br;
$title = str_replace(array("\r","\n"),array('',''),$title);
$result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
logger('linkinfo (unparsed): returns: ' . $result);
echo $result;
killme();
}
$siteinfo = self::parseurl_getsiteinfo($url);
// If the site uses this platform, use zrl rather than url so they get zids sent to them by default
if(is_matrix_url($url))
$template = str_replace('url','zrl',$template);
if($siteinfo["title"] == "") {
echo sprintf($template,$url,$url,'') . $str_tags;
killme();
@@ -156,19 +161,19 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$text = $siteinfo["text"];
$title = $siteinfo["title"];
}
$image = "";
if(is_array($siteinfo["images"]) && count($siteinfo["images"])){
/* Execute below code only if image is present in siteinfo */
$total_images = 0;
$max_images = get_config('system','max_bookmark_images');
if($max_images === false)
$max_images = 2;
else
$max_images = intval($max_images);
foreach ($siteinfo["images"] as $imagedata) {
if ($url) {
$image .= sprintf('[url=%s]', $url);
@@ -183,57 +188,57 @@ class Linkinfo extends \Zotlabs\Web\Controller {
break;
}
}
if(strlen($text)) {
$text = $br.'[quote]'.trim($text).'[/quote]'.$br ;
}
if($image) {
$text = $br.$br.$image.$text;
}
$title = str_replace(array("\r","\n"),array('',''),$title);
$result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
logger('linkinfo: returns: ' . $result, LOGGER_DEBUG);
echo trim($result);
killme();
}
public static function deletexnode(&$doc, $node) {
$xpath = new \DomXPath($doc);
$list = $xpath->query("//".$node);
foreach ($list as $child)
$child->parentNode->removeChild($child);
}
public static function completeurl($url, $scheme) {
$urlarr = parse_url($url);
if (isset($urlarr["scheme"]))
return($url);
$schemearr = parse_url($scheme);
$complete = $schemearr["scheme"]."://".$schemearr["host"];
if ($schemearr["port"] != "")
$complete .= ":".$schemearr["port"];
if(strpos($urlarr['path'],'/') !== 0)
$complete .= '/';
$complete .= $urlarr["path"];
if ($urlarr["query"] != "")
$complete .= "?".$urlarr["query"];
if ($urlarr["fragment"] != "")
$complete .= "#".$urlarr["fragment"];
return($complete);
}
@@ -251,7 +256,7 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$p = substr($m,strpos($m,'/')+1);
// get the channel to check permissions
$u = channelx_by_nick($nick);
if($u && $p) {
@@ -272,18 +277,18 @@ class Linkinfo extends \Zotlabs\Web\Controller {
return EMPTY_STR;
}
public static function parseurl_getsiteinfo($url) {
$siteinfo = array();
$result = z_fetch_url($url,false,0,array('novalidate' => true));
if(! $result['success'])
return $siteinfo;
$header = $result['header'];
$body = $result['body'];
// Check codepage in HTTP headers or HTML if not exist
$cp = (preg_match('/Content-Type: text\/html; charset=(.+)\r\n/i', $header, $o) ? $o[1] : '');
if(empty($cp))
@@ -291,10 +296,10 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$body = mb_convert_encoding($body, 'UTF-8', $cp);
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
$doc = new \DOMDocument();
@$doc->loadHTML($body);
self::deletexnode($doc, 'style');
self::deletexnode($doc, 'script');
self::deletexnode($doc, 'option');
@@ -306,14 +311,14 @@ class Linkinfo extends \Zotlabs\Web\Controller {
self::deletexnode($doc, 'h6');
self::deletexnode($doc, 'ol');
self::deletexnode($doc, 'ul');
$xpath = new \DomXPath($doc);
//$list = $xpath->query("head/title");
$list = $xpath->query("//title");
foreach ($list as $node)
$siteinfo["title"] = html_entity_decode($node->nodeValue, ENT_QUOTES, "UTF-8");
//$list = $xpath->query("head/meta[@name]");
$list = $xpath->query("//meta[@name]");
foreach ($list as $node) {
@@ -321,9 +326,9 @@ class Linkinfo extends \Zotlabs\Web\Controller {
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
switch (strtolower($attr["name"])) {
case "fulltitle":
$siteinfo["title"] = trim($attr["content"]);
@@ -365,7 +370,7 @@ class Linkinfo extends \Zotlabs\Web\Controller {
break;
}
}
//$list = $xpath->query("head/meta[@property]");
$list = $xpath->query("//meta[@property]");
foreach ($list as $node) {
@@ -373,9 +378,9 @@ class Linkinfo extends \Zotlabs\Web\Controller {
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
switch (strtolower($attr["property"])) {
case "og:image":
$siteinfo["image"] = $attr["content"];
@@ -388,7 +393,7 @@ class Linkinfo extends \Zotlabs\Web\Controller {
break;
}
}
if ($siteinfo["image"] == "") {
$list = $xpath->query("//img[@src]");
foreach ($list as $node) {
@@ -396,10 +401,10 @@ class Linkinfo extends \Zotlabs\Web\Controller {
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$src = self::completeurl($attr["src"], $url);
$photodata = @getimagesize($src);
if (($photodata) && ($photodata[0] > 150) and ($photodata[1] > 150)) {
if ($photodata[0] > 300) {
$photodata[1] = round($photodata[1] * (300 / $photodata[0]));
@@ -413,36 +418,36 @@ class Linkinfo extends \Zotlabs\Web\Controller {
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
}
} else {
$src = self::completeurl($siteinfo["image"], $url);
unset($siteinfo["image"]);
$photodata = @getimagesize($src);
if (($photodata) && ($photodata[0] > 10) and ($photodata[1] > 10))
$siteinfo["images"][] = array("src"=>$src,
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
if ($siteinfo["text"] == "") {
$text = "";
$list = $xpath->query("//div[@class='article']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
if ($text == "") {
$list = $xpath->query("//div[@class='content']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
// If none text was found then take the paragraph content
if ($text == "") {
$list = $xpath->query("//p");
@@ -450,21 +455,21 @@ class Linkinfo extends \Zotlabs\Web\Controller {
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
if ($text != "") {
$text = trim(str_replace(array("\n", "\r"), array(" ", " "), $text));
while (strpos($text, " "))
$text = trim(str_replace(" ", " ", $text));
$text = substr(html_entity_decode($text, ENT_QUOTES, "UTF-8"), 0, 350);
$siteinfo["text"] = rtrim(substr($text, 0, strrpos($text, " ")), "?.,:;!-") . '...';
}
}
return($siteinfo);
}
private static function arr_add_hashes(&$item,$k) {
$item = '#' . $item;

View File

@@ -28,9 +28,8 @@ class Locs extends Controller {
return;
}
q("UPDATE hubloc SET hubloc_primary = 0 WHERE hubloc_primary = 1 AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
dbesc($channel['channel_hash']),
dbesc($channel['channel_portable_id'])
q("UPDATE hubloc SET hubloc_primary = 0 WHERE hubloc_primary = 1 AND hubloc_hash = '%s'",
dbesc($channel['channel_hash'])
);
q("UPDATE hubloc SET hubloc_primary = 1 WHERE hubloc_id = %d AND hubloc_hash = '%s'",
@@ -81,10 +80,9 @@ class Locs extends Controller {
}
}
q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND hubloc_hash = '%s'",
dbesc($r[0]['hubloc_id_url']),
dbesc($channel['channel_hash']),
dbesc($channel['channel_portable_id'])
dbesc($channel['channel_hash'])
);
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
return;
@@ -118,11 +116,6 @@ class Locs extends Controller {
return;
}
for($x = 0; $x < count($r); $x ++) {
$r[$x]['primary'] = (intval($r[$x]['hubloc_primary']) ? true : false);
$r[$x]['deleted'] = (intval($r[$x]['hubloc_deleted']) ? true : false);
}
$o = replace_macros(get_markup_template('locmanage.tpl'), array(
'$header' => t('Manage Channel Locations'),
'$loc' => t('Location'),
@@ -134,7 +127,8 @@ class Locs extends Controller {
'$sync_text' => t('Please wait several minutes between consecutive operations.'),
'$drop_text' => t('When possible, drop a location by logging into that website/hub and removing your channel.'),
'$last_resort' => t('Use this form to drop the location if the hub is no longer operating.'),
'$hubs' => $r
'$hubs' => $r,
'$base_url' => z_root()
));
return $o;

View File

@@ -40,7 +40,7 @@ class Magic extends Controller {
goaway($dest);
}
$basepath = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '');
$basepath = $parsed['scheme'] . '://' . $parsed['host'] . (isset($parsed['port']) ? ':' . $parsed['port'] : '');
$owapath = SConfig::get($basepath,'system','openwebauth', $basepath . '/owa');
// This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating.
@@ -110,6 +110,7 @@ class Magic extends Controller {
$headers['(request-target)'] = 'post ' . '/owa';
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
$redirects = 0;
$x = z_post_url($owapath,$data,$redirects,[ 'headers' => $headers ]);
logger('owa fetch returned: ' . print_r($x,true),LOGGER_DATA);
if ($x['success']) {

View File

@@ -5,18 +5,18 @@ namespace Zotlabs\Module;
class Manage extends \Zotlabs\Web\Controller {
function get() {
if((! get_account_id()) || ($_SESSION['delegate'])) {
notice( t('Permission denied.') . EOL);
return;
}
nav_set_selected('Channel Manager', 'settings/manage');
require_once('include/security.php');
$change_channel = ((argc() > 1) ? intval(argv(1)) : 0);
if((argc() > 2) && (argv(2) === 'default')) {
$r = q("select channel_id from channel where channel_id = %d and channel_account_id = %d limit 1",
intval($change_channel),
@@ -31,7 +31,7 @@ class Manage extends \Zotlabs\Web\Controller {
goaway(z_root() . '/manage');
}
if($change_channel) {
$r = change_channel($change_channel);
@@ -45,29 +45,29 @@ class Manage extends \Zotlabs\Web\Controller {
}
goaway(z_root());
}
$channels = null;
$r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and channel_removed = 0 order by channel_name ",
intval(get_account_id())
);
$account = \App::get_account();
if($r && count($r)) {
$channels = $r;
for($x = 0; $x < count($channels); $x ++) {
$channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']);
$channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : '');
$channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : '');
$channels[$x]['default_links'] = '1';
/* this is not currently implemented in the UI and probably should not (performance)
$c = q("SELECT id, item_wall FROM item
WHERE item_unseen = 1 and uid = %d " . item_normal(),
intval($channels[$x]['channel_id'])
);
if($c) {
if($c) {
foreach ($c as $it) {
if(intval($it['item_wall']))
$channels[$x]['home'] ++;
@@ -75,25 +75,16 @@ class Manage extends \Zotlabs\Web\Controller {
$channels[$x]['network'] ++;
}
}
*/
$intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
intval($channels[$x]['channel_id'])
);
if($intr)
$channels[$x]['intros'] = intval($intr[0]['total']);
$mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
intval($channels[$x]['channel_id']),
dbesc($channels[$x]['channel_hash'])
);
if($mails)
$channels[$x]['mail'] = intval($mails[0]['total']);
/* this is not currently implemented in the UI and probably should not (performance)
$events = q("SELECT etype, dtstart, adjust FROM event
WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
ORDER BY dtstart ASC ",
@@ -101,7 +92,7 @@ class Manage extends \Zotlabs\Web\Controller {
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
);
if($events) {
$channels[$x]['all_events'] = count($events);
@@ -126,9 +117,10 @@ class Manage extends \Zotlabs\Web\Controller {
}
}
}
*/
}
}
}
$r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0",
intval(get_account_id())
@@ -140,23 +132,23 @@ class Manage extends \Zotlabs\Web\Controller {
else {
$channel_usage_message = '';
}
$create = array( 'new_channel', t('Create a new channel'), t('Create New'));
$delegates = null;
if(local_channel()) {
$delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where
$delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where
abook_channel = %d and abook_xchan in ( select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'delegate' and v = '1' )",
intval(local_channel()),
intval(local_channel())
);
}
if($delegates) {
for($x = 0; $x < count($delegates); $x ++) {
$delegates[$x]['link'] = 'magic?f=&bdest=' . bin2hex($delegates[$x]['xchan_url'])
$delegates[$x]['link'] = 'magic?f=&bdest=' . bin2hex($delegates[$x]['xchan_url'] . '?zid=' . get_my_address() . '&delegate=' . urlencode($delegates[$x]['xchan_addr']))
. '&delegate=' . urlencode($delegates[$x]['xchan_addr']);
$delegates[$x]['channel_name'] = $delegates[$x]['xchan_name'];
$delegates[$x]['delegate'] = 1;
@@ -165,9 +157,9 @@ class Manage extends \Zotlabs\Web\Controller {
else {
$delegates = null;
}
$o = replace_macros(get_markup_template('channels.tpl'), array(
'$header' => t('Channel Manager'),
'$header' => t('Channels'),
'$msg_selected' => t('Current Channel'),
'$selected' => local_channel(),
'$desc' => ((count($channels) > 1 || $delegates) ? t('Switch to one of your channels by selecting it.') : ''),
@@ -175,15 +167,14 @@ class Manage extends \Zotlabs\Web\Controller {
'$msg_make_default' => t('Make Default'),
'$create' => $create,
'$all_channels' => $channels,
'$mail_format' => t('%d new messages'),
'$intros_format' => t('%d new introductions'),
'$channel_usage_message' => $channel_usage_message,
'$delegated_desc' => t('Delegated Channel'),
'$delegates' => $delegates
));
return $o;
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\System;
class Manifest extends Controller {
function init() {
$ret = [
'name' => ucfirst(System::get_platform_name()),
'short_name' => ucfirst(System::get_platform_name()),
'icons' => [
[ 'src' => '/images/app/hz-72.png', 'sizes' => '72x72', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-96.png', 'sizes' => '96x96', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-128.png', 'sizes' => '128x128', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-144.png', 'sizes' => '144x144', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-152.png', 'sizes' => '152x152', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-192.png', 'sizes' => '192x192', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-348.png', 'sizes' => '384x384', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-512.png', 'sizes' => '512x512', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz.svg', 'sizes' => '64x64', 'type' => 'image/xml+svg' ]
],
'theme_color' => '#343a40',
'scope' => '/',
'start_url' => z_root(),
'display' => 'standalone',
'share_target' => [
'action' => '/rpost',
'method' => 'POST',
'enctype' => 'multipart/form-data',
'params' => [
'title' => 'title',
'text' => 'body',
'url' => 'url',
'files' => [
[ 'name' => 'userfile',
'accept' => [ 'image/*', 'audio/*', 'video/*', 'text/*', 'application/*' ]
]
]
]
]
];
json_return_and_die($ret,'application/manifest+json');
}
}

View File

@@ -1,108 +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 Message extends \Zotlabs\Web\Controller {
function get() {
$o = '';
nav_set_selected('messages');
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';
/*
if((argc() == 3) && (argv(1) === 'dropconv')) {
if(! intval(argv(2)))
return;
$cmd = argv(1);
$r = private_messages_drop(local_channel(), argv(2), true);
if($r)
info( t('Conversation removed.') . EOL );
goaway(z_root() . '/mail/combined' );
}
if(argc() == 2) {
switch(argv(1)) {
case 'combined':
$mailbox = 'combined';
$header = t('Conversations');
break;
case 'inbox':
$mailbox = 'inbox';
$header = t('Received Messages');
break;
case 'outbox':
$mailbox = 'outbox';
$header = t('Sent Messages');
break;
default:
break;
}
// private_messages_list() can do other more complicated stuff, for now keep it simple
$r = private_messages_list(local_channel(), $mailbox, \App::$pager['start'], \App::$pager['itemspage']);
if(! $r) {
info( t('No messages.') . EOL);
return $o;
}
$messages = array();
foreach($r as $rr) {
$messages[] = array(
'id' => $rr['id'],
'from_name' => $rr['from']['xchan_name'],
'from_url' => chanlink_hash($rr['from_xchan']),
'from_photo' => $rr['from']['xchan_photo_s'],
'to_name' => $rr['to']['xchan_name'],
'to_url' => chanlink_hash($rr['to_xchan']),
'to_photo' => $rr['to']['xchan_photo_s'],
'subject' => (($rr['seen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'),
'delete' => t('Delete conversation'),
'body' => zidify_links(smilies(bbcode($rr['body']))),
'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], t('D, d M Y - g:i A')),
'seen' => $rr['seen']
);
}
$tpl = get_markup_template('mail_head.tpl');
$o = replace_macros($tpl, array(
'$header' => $header,
'$messages' => $messages
));
$o .= alt_pager(count($r));
return $o;
return;
}
*/
return;
}
}

View File

@@ -14,36 +14,36 @@ require_once('include/items.php');
class Mood extends Controller {
function init() {
if(! local_channel())
return;
if(! Apps::system_app_installed(local_channel(), 'Mood')) {
return;
}
$uid = local_channel();
$channel = App::get_channel();
$verb = notags(trim($_GET['verb']));
if(! $verb)
if(! $verb)
return;
$verbs = get_mood_verbs();
if(! array_key_exists($verb,$verbs))
return;
$activity = ACTIVITY_MOOD . '#' . urlencode($verb);
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : 0);
logger('mood: verb ' . $verb, LOGGER_DEBUG);
if($parent) {
$r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid
$r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid
from item where id = %d and parent = %d and uid = %d limit 1",
intval($parent),
intval($parent),
@@ -59,24 +59,24 @@ class Mood extends Controller {
}
}
else {
$private = 0;
$allow_cid = $channel['channel_allow_cid'];
$allow_gid = $channel['channel_allow_gid'];
$deny_cid = $channel['channel_deny_cid'];
$deny_gid = $channel['channel_deny_gid'];
}
$poster = App::get_observer();
$uuid = item_message_id();
$mid = z_root() . '/item/' . $uuid;
$action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]);
$action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]);
$arr = array();
$arr['aid'] = get_account_id();
$arr['uid'] = $uid;
$arr['uuid'] = $uuid;
@@ -97,31 +97,31 @@ class Mood extends Controller {
$arr['item_unseen'] = 1;
if(! $parent_mid)
$item['item_thread_top'] = 1;
if ((! $arr['plink']) && intval($arr['item_thread_top'])) {
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
}
$post = item_store($arr);
$item_id = $post['item_id'];
if($item_id) {
\Zotlabs\Daemon\Master::Summon(array('Notifier','activity', $item_id));
}
call_hooks('post_local_end', $arr);
if($_SESSION['return_url'])
goaway(z_root() . '/' . $_SESSION['return_url']);
return;
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
@@ -130,26 +130,24 @@ class Mood extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Mood')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Mood App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Set your current mood and tell your friends');
return $o;
$papp = Apps::get_papp('Mood');
return Apps::app_render($papp, 'module');
}
nav_set_selected('Mood');
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : '0');
$verbs = get_mood_verbs();
$shortlist = array();
foreach($verbs as $k => $v)
if($v !== 'NOTRANSLATION')
$shortlist[] = array($k,$v);
$tpl = get_markup_template('mood_content.tpl');
$o = replace_macros($tpl,array(
'$title' => t('Mood'),
'$desc' => t('Set your current mood and tell your friends'),
@@ -157,9 +155,9 @@ class Mood extends Controller {
'$parent' => $parent,
'$submit' => t('Submit'),
));
return $o;
}
}

View File

@@ -22,11 +22,11 @@ class Network extends \Zotlabs\Web\Controller {
$search = $_GET['search'] ?? '';
if(in_array(substr($search, 0, 1),[ '@', '!', '?']) || strpos($search, 'https://') === 0)
if(in_array(substr($search, 0, 1), [ '@', '!', '?']) || strpos($search, 'https://') === 0)
goaway(z_root() . '/search?f=&search=' . $search);
if(count($_GET) < 2) {
$network_options = get_pconfig(local_channel(),'system','network_page_default');
$network_options = get_pconfig(local_channel(), 'system', 'network_page_default');
if($network_options)
goaway(z_root() . '/network?f=&' . $network_options);
}
@@ -84,7 +84,7 @@ class Network extends \Zotlabs\Web\Controller {
$search = $_GET['search'] ?? '';
if($search) {
if(strpos($search,'#') === 0) {
if(strpos($search, '#') === 0) {
$hashtags = substr($search,1);
$search = '';
}
@@ -114,31 +114,31 @@ class Network extends \Zotlabs\Web\Controller {
$def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>');
}
$default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1));
$default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1));
$default_cmin = ((Apps::system_app_installed(local_channel(), 'Affinity Tool')) ? get_pconfig(local_channel(), 'affinity', 'cmin', 0) : (-1));
$default_cmax = ((Apps::system_app_installed(local_channel(), 'Affinity Tool')) ? get_pconfig(local_channel(), 'affinity', 'cmax', 99) : (-1));
$cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0);
$star = ((x($_GET,'star')) ? intval($_GET['star']) : 0);
$liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0);
$conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0);
$spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0);
$cmin = ((array_key_exists('cmin',$_GET)) ? intval($_GET['cmin']) : $default_cmin);
$cmax = ((array_key_exists('cmax',$_GET)) ? intval($_GET['cmax']) : $default_cmax);
$file = ((x($_GET,'file')) ? $_GET['file'] : '');
$xchan = ((x($_GET,'xchan')) ? $_GET['xchan'] : '');
$net = ((x($_GET,'net')) ? $_GET['net'] : '');
$pf = ((x($_GET,'pf')) ? $_GET['pf'] : '');
$unseen = ((x($_GET,'unseen')) ? $_GET['unseen'] : '');
$cid = ((x($_GET, 'cid')) ? intval($_GET['cid']) : 0);
$star = ((x($_GET, 'star')) ? intval($_GET['star']) : 0);
$liked = ((x($_GET, 'liked')) ? intval($_GET['liked']) : 0);
$conv = ((x($_GET, 'conv')) ? intval($_GET['conv']) : 0);
$spam = ((x($_GET, 'spam')) ? intval($_GET['spam']) : 0);
$cmin = ((array_key_exists('cmin', $_GET)) ? intval($_GET['cmin']) : $default_cmin);
$cmax = ((array_key_exists('cmax', $_GET)) ? intval($_GET['cmax']) : $default_cmax);
$file = ((x($_GET, 'file')) ? $_GET['file'] : '');
$xchan = ((x($_GET, 'xchan')) ? $_GET['xchan'] : '');
$net = ((x($_GET, 'net')) ? $_GET['net'] : '');
$pf = ((x($_GET, 'pf')) ? $_GET['pf'] : '');
$unseen = ((x($_GET, 'unseen')) ? $_GET['unseen'] : '');
if (Apps::system_app_installed(local_channel(),'Affinity Tool')) {
$affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1));
if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) {
$affinity_locked = intval(get_pconfig(local_channel(), 'affinity', 'lock', 1));
if ($affinity_locked) {
set_pconfig(local_channel(),'affinity','cmin',$cmin);
set_pconfig(local_channel(),'affinity','cmax',$cmax);
set_pconfig(local_channel(), 'affinity', 'cmin', $cmin);
set_pconfig(local_channel(), 'affinity', 'cmax', $cmax);
}
}
if(x($_GET,'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen)
if(x($_GET, 'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen)
$nouveau = true;
$cid_r = [];
@@ -164,8 +164,8 @@ class Network extends \Zotlabs\Web\Controller {
// search terms header
if($search || $hashtags) {
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => t('Search Results For:') . ' ' . (($search) ? htmlspecialchars($search, ENT_COMPAT,'UTF-8') : '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8'))
$o .= replace_macros(get_markup_template('section_title.tpl'), array(
'$title' => t('Search Results For:') . ' ' . (($search) ? htmlspecialchars($search, ENT_COMPAT, 'UTF-8') : '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8'))
));
}
@@ -193,7 +193,7 @@ class Network extends \Zotlabs\Web\Controller {
$x = array(
'is_owner' => true,
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
'allow_location' => ((intval(get_pconfig($channel['channel_id'], 'system', 'use_browser_location'))) ? '1' : ''),
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
'lockstate' => (($private_editing || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
@@ -209,7 +209,7 @@ class Network extends \Zotlabs\Web\Controller {
'reset' => t('Reset form')
);
$status_editor = status_editor($a,$x,false,'Network');
$status_editor = status_editor($a, $x, false, 'Network');
$o .= $status_editor;
}
@@ -221,7 +221,7 @@ class Network extends \Zotlabs\Web\Controller {
$sql_options = (($star)
? " and item_starred = 1 "
? ' and item_starred = 1 '
: '');
$sql_nets = '';
@@ -235,7 +235,7 @@ class Network extends \Zotlabs\Web\Controller {
$contact_str = '';
$contacts = group_get_members($group);
if($contacts) {
$contact_str = ids_to_querystr($contacts,'xchan',true);
$contact_str = ids_to_querystr($contacts, 'xchan', true);
}
else {
$contact_str = " '0' ";
@@ -249,7 +249,7 @@ class Network extends \Zotlabs\Web\Controller {
$x = group_rec_byhash(local_channel(), $group_hash);
if($x) {
$title = replace_macros(get_markup_template("section_title.tpl"),array(
$title = replace_macros(get_markup_template('section_title.tpl'), array(
'$title' => t('Privacy group: ') . $x['gname']
));
}
@@ -289,10 +289,10 @@ class Network extends \Zotlabs\Web\Controller {
// This is for threaded view cid queries (e.g. if a forum is selected from the forum filter)
$ttype = (($pf) ? TERM_FORUM : TERM_MENTION);
$p1 = q("SELECT DISTINCT parent FROM item WHERE uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' OR owner_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' ) $item_normal ");
$p2 = q("SELECT oid AS parent FROM term WHERE uid = " . intval(local_channel()) . " AND ttype = $ttype AND term = '" . dbesc($cid_r[0]['xchan_name']) . "'");
$p1 = dbq("SELECT DISTINCT parent FROM item WHERE uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' OR owner_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' ) $item_normal ");
$p2 = dbq("SELECT oid AS parent FROM term WHERE uid = " . intval(local_channel()) . " AND ttype = $ttype AND term = '" . dbesc($cid_r[0]['xchan_name']) . "'");
$p_str = ids_to_querystr(array_merge($p1,$p2),'parent');
$p_str = ids_to_querystr(array_merge($p1, $p2), 'parent');
if(! $p_str)
killme();
@@ -300,7 +300,7 @@ class Network extends \Zotlabs\Web\Controller {
}
}
$title = replace_macros(get_markup_template("section_title.tpl"),array(
$title = replace_macros(get_markup_template('section_title.tpl'), array(
'$title' => '<a href="' . zid($cid_r[0]['xchan_url']) . '" ><img src="' . zid($cid_r[0]['xchan_photo_s']) . '" alt="' . urlencode($cid_r[0]['xchan_name']) . '" /></a> <a href="' . zid($cid_r[0]['xchan_url']) . '" >' . $cid_r[0]['xchan_name'] . '</a>'
));
@@ -314,7 +314,7 @@ class Network extends \Zotlabs\Web\Controller {
if($r) {
$item_thread_top = '';
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($xchan) . "' or owner_xchan = '" . dbesc($xchan) . "' ) $item_normal ) ";
$title = replace_macros(get_markup_template("section_title.tpl"),array(
$title = replace_macros(get_markup_template("section_title.tpl"), array(
'$title' => '<a href="' . zid($r[0]['xchan_url']) . '" ><img src="' . zid($r[0]['xchan_photo_s']) . '" alt="' . urlencode($r[0]['xchan_name']) . '" /></a> <a href="' . zid($r[0]['xchan_url']) . '" >' . $r[0]['xchan_name'] . '</a>'
));
@@ -345,13 +345,13 @@ class Network extends \Zotlabs\Web\Controller {
$sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
$sql_extra2 = (($nouveau) ? '' : " AND item.parent = item.id ");
$sql_extra2 = (($nouveau) ? '' : ' AND item.parent = item.id ');
$sql_extra3 = (($nouveau) ? '' : $sql_extra3);
if(x($_GET,'search')) {
if(x($_GET, 'search')) {
$search = escape_tags($_GET['search']);
if(strpos($search,'#') === 0) {
$sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG);
if(strpos($search, '#') === 0) {
$sql_extra .= term_query('item', substr($search, 1), TERM_HASHTAG, TERM_COMMUNITYTAG);
}
else {
$sql_extra .= sprintf(" AND (item.body like '%s' OR item.title like '%s') ",
@@ -368,8 +368,8 @@ class Network extends \Zotlabs\Web\Controller {
// The name 'verb' is a holdover from the earlier XML
// ActivityStreams specification.
if (substr($verb,0,1) === '.') {
$verb = substr($verb,1);
if (substr($verb, 0, 1) === '.') {
$verb = substr($verb, 1);
$sql_extra .= sprintf(" AND item.obj_type like '%s' ",
dbesc(protect_sprintf('%' . $verb . '%'))
);
@@ -382,12 +382,16 @@ class Network extends \Zotlabs\Web\Controller {
}
if(strlen($file)) {
$sql_extra .= term_query('item',$file,TERM_FILE);
$sql_extra .= term_query('item', $file, TERM_FILE);
}
if ($dm) {
$sql_extra .= " AND item_private = 2 ";
$sql_extra .= ' AND item_private = 2 ';
}
else {
$sql_extra .= ' AND item_private IN (0, 1) ';
}
if($conv) {
$item_thread_top = '';
@@ -401,38 +405,38 @@ class Network extends \Zotlabs\Web\Controller {
}
else {
$itemspage = get_pconfig(local_channel(),'system','itemspage');
$itemspage = get_pconfig(local_channel(), 'system', 'itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
}
// cmin and cmax are both -1 when the affinity tool is disabled
if(($cmin != (-1)) || ($cmax != (-1))) {
if(($cmin !== (-1)) || ($cmax !== (-1))) {
// Not everybody who shows up in the network stream will be in your address book.
// By default those that aren't are assumed to have closeness = 99; but this isn't
// recorded anywhere. So if cmax is 99, we'll open the search up to anybody in
// the stream with a NULL address book entry.
$sql_nets .= " AND ";
$sql_nets .= ' AND ';
if($cmax == 99)
$sql_nets .= " ( ";
if($cmax === 99)
$sql_nets .= ' ( ';
$sql_nets .= "( abook.abook_closeness >= " . intval($cmin) . " ";
$sql_nets .= " AND abook.abook_closeness <= " . intval($cmax) . " ) ";
$sql_nets .= '( abook.abook_closeness >= ' . intval($cmin) . ' ';
$sql_nets .= ' AND abook.abook_closeness <= ' . intval($cmax) . ' ) ';
if($cmax == 99)
$sql_nets .= " OR abook.abook_closeness IS NULL ) ";
if($cmax === 99)
$sql_nets .= ' OR abook.abook_closeness IS NULL ) ';
}
$net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : '');
$net_query = (($net) ? ' left join xchan on xchan_hash = author_xchan ' : '');
$net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : '');
$abook_uids = " and abook.abook_channel = " . local_channel() . " ";
$uids = " and item.uid = " . local_channel() . " ";
$abook_uids = ' and abook.abook_channel = ' . local_channel() . ' ';
$uids = ' and item.uid = ' . local_channel() . ' ';
if(feature_enabled(local_channel(), 'network_list_mode'))
$page_mode = 'list';
@@ -461,7 +465,7 @@ class Network extends \Zotlabs\Web\Controller {
if($nouveau && $load) {
// "New Item View" - show all items unthreaded in reverse created date order
$items = q("SELECT item.*, item.id AS item_id, created FROM item
$items = dbq("SELECT item.*, item.id AS item_id, created FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
$net_query
WHERE true $uids $item_normal
@@ -471,26 +475,26 @@ class Network extends \Zotlabs\Web\Controller {
ORDER BY item.created DESC $pager_sql "
);
$parents_str = ids_to_querystr($items,'item_id');
$parents_str = ids_to_querystr($items, 'item_id');
require_once('include/items.php');
xchan_query($items);
$items = fetch_post_tags($items,true);
$items = fetch_post_tags($items, true);
}
elseif($update) {
// Normal conversation view
if($order === 'post')
$ordering = "created";
$ordering = 'created';
else
$ordering = "commented";
$ordering = 'commented';
if($load) {
// Fetch a page full of parent items for this page
$r = q("SELECT item.parent AS item_id FROM item
$r = dbq("SELECT item.parent AS item_id FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
$net_query
WHERE true $uids $item_thread_top $item_normal
@@ -504,31 +508,28 @@ class Network extends \Zotlabs\Web\Controller {
else {
// this is an update
$r = q("SELECT item.parent AS item_id FROM item
$r = dbq("SELECT item.parent AS item_id FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
$net_query
WHERE true $uids $item_normal_update $simple_update
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_options $sql_nets $net_query2"
$sql_extra3 $sql_extra $sql_options $sql_nets $net_query2 "
);
}
// Then fetch all the children of the parents that are on this page
if($r) {
$parents_str = ids_to_querystr($r,'item_id');
$items = q("SELECT item.*, item.id AS item_id FROM item
$parents_str = ids_to_querystr($r, 'item_id');
$items = dbq("SELECT item.*, item.id AS item_id FROM item
WHERE true $uids $item_normal
AND item.parent IN ( %s )
$sql_extra ",
dbesc($parents_str)
AND item.parent IN ( $parents_str )
$sql_extra "
);
xchan_query($items,true);
$items = fetch_post_tags($items,true);
$items = conv_sort($items,$ordering);
xchan_query($items, true);
$items = fetch_post_tags($items, true);
$items = conv_sort($items, $ordering);
}
else {
$items = array();
@@ -546,7 +547,7 @@ class Network extends \Zotlabs\Web\Controller {
// 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');
$maxheight = get_pconfig(local_channel(), 'system', 'network_divmore_height');
if(! $maxheight)
$maxheight = 400;
@@ -591,7 +592,7 @@ class Network extends \Zotlabs\Web\Controller {
));
}
$o .= conversation($items,$mode,$update,$page_mode);
$o .= conversation($items, $mode, $update, $page_mode);
if(($items) && (! $update))
$o .= alt_pager(count($items));

View File

@@ -1,6 +1,8 @@
<?php
namespace Zotlabs\Module;
use URLify;
require_once('include/channel.php');
require_once('include/permissions.php');
@@ -13,7 +15,6 @@ class New_channel extends \Zotlabs\Web\Controller {
$cmd = ((argc() > 1) ? argv(1) : '');
if($cmd === 'autofill.json') {
require_once('library/urlify/URLify.php');
$result = array('error' => false, 'message' => '');
$n = trim($_REQUEST['name']);
@@ -24,7 +25,7 @@ class New_channel extends \Zotlabs\Web\Controller {
}
if((! $x) || strlen($x) > 64)
$x = strtolower(\URLify::transliterate($n));
$x = strtolower(URLify::transliterate($n));
$test = array();
@@ -46,7 +47,6 @@ class New_channel extends \Zotlabs\Web\Controller {
}
if($cmd === 'checkaddr.json') {
require_once('library/urlify/URLify.php');
$result = array('error' => false, 'message' => '');
$n = trim($_REQUEST['nick']);
if(! $n) {
@@ -60,7 +60,7 @@ class New_channel extends \Zotlabs\Web\Controller {
}
if((! $x) || strlen($x) > 64)
$x = strtolower(\URLify::transliterate($n));
$x = strtolower(URLify::transliterate($n));
$test = array();

View File

@@ -19,7 +19,12 @@ class Notes extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Notes'))
return EMPTY_STR;
$ret = array('success' => true);
$ret = [
'success' => false,
'html' => ''
];
if(array_key_exists('note_text',$_REQUEST)) {
$body = escape_tags($_REQUEST['note_text']);
@@ -33,12 +38,15 @@ class Notes extends Controller {
set_pconfig(local_channel(),'notes','text.bak',$old_text);
}
set_pconfig(local_channel(),'notes','text',$body);
$ret['html'] = bbcode($body);
$ret['success'] = true;
}
// push updates to channel clones
if((argc() > 1) && (argv(1) === 'sync')) {
require_once('include/zot.php');
Libsync::build_sync_packet();
}
@@ -52,11 +60,9 @@ class Notes extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Notes')) {
//Do not display any associated widgets at this point
App::$pdl = EMPTY_STR;
$o = '<b>' . t('Notes App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('A simple notes app with a widget (note: notes are not encrypted)');
return $o;
App::$pdl = '';
$papp = Apps::get_papp('Notes');
return Apps::app_render($papp, 'module');
}
$w = new \Zotlabs\Widget\Notes;

View File

@@ -8,10 +8,58 @@ class Notifications extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
// ajax mark all unseen items read
if(x($_REQUEST, 'markRead')) {
switch($_REQUEST['markRead']) {
case 'dm':
$r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_private = 2",
intval(local_channel())
);
break;
case 'network':
$r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_private IN (0, 1)",
intval(local_channel())
);
break;
case 'home':
$r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_wall = 1 AND item_private IN (0, 1)",
intval(local_channel())
);
break;
case 'all_events':
$evdays = intval(get_pconfig(local_channel(), 'system', 'evdays', 3));
$r = q("UPDATE event SET dismissed = 1 WHERE uid = %d AND dismissed = 0 AND dtstart < '%s' AND dtstart > '%s' ",
intval(local_channel()),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
);
break;
case 'notify':
$r = q("UPDATE notify SET seen = 1 WHERE seen = 0 AND uid = %d",
intval(local_channel())
);
break;
case 'pubs':
unset($_SESSION['static_loadtime']);
break;
default:
break;
}
killme();
}
// ajax mark all comments of a parent item read
if(x($_REQUEST, 'markItemRead') && local_channel()) {
$r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND parent = %d",
intval(local_channel()),
intval($_REQUEST['markItemRead'])
);
killme();
}
nav_set_selected('Notifications');
$o = '';

View File

@@ -1,14 +1,38 @@
<?php
namespace Zotlabs\Module;
use \Zotlabs\Lib\PConfig;
use \Zotlabs\Web\Controller;
class Notify extends \Zotlabs\Web\Controller {
class Notify extends Controller {
function init() {
if(! local_channel())
return;
if($_REQUEST['notify_id']) {
$update_notices_per_parent = PConfig::Get(local_channel(), 'system', 'update_notices_per_parent', 1);
if($update_notices_per_parent) {
$r = q("SELECT parent FROM notify WHERE id = %d AND uid = %d",
intval($_REQUEST['notify_id']),
intval(local_channel())
);
q("update notify set seen = 1 where parent = '%s' and uid = %d",
dbesc($r[0]['parent']),
intval(local_channel())
);
}
else {
q("update notify set seen = 1 where id = %d and uid = %d",
intval($_REQUEST['notify_id']),
intval(local_channel())
);
}
killme();
}
if(argc() > 2 && argv(1) === 'view' && intval(argv(2))) {
$r = q("select * from notify where id = %d and uid = %d limit 1",
intval(argv(2)),
@@ -29,24 +53,24 @@ class Notify extends \Zotlabs\Web\Controller {
}
goaway(z_root());
}
}
function get() {
if(! local_channel())
return login();
$notif_tpl = get_markup_template('notifications.tpl');
$not_tpl = get_markup_template('notify.tpl');
require_once('include/bbcode.php');
$r = q("SELECT * from notify where uid = %d and seen = 0 order by created desc",
intval(local_channel())
);
if($r) {
foreach ($r as $it) {
$notif_content .= replace_macros($not_tpl,array(
@@ -56,18 +80,18 @@ class Notify extends \Zotlabs\Web\Controller {
'$item_when' => relative_date($it['created'])
));
}
}
}
else {
$notif_content .= t('No more system notifications.');
}
$o .= replace_macros($notif_tpl,array(
'$notif_header' => t('System Notifications'),
'$tabs' => '', // $tabs,
'$notif_content' => $notif_content,
));
return $o;
}
}

View File

@@ -17,22 +17,22 @@ class Oauth extends Controller {
if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager'))
return;
if(x($_POST,'remove')){
check_form_security_token_redirectOnErr('/oauth', 'oauth');
$key = $_POST['remove'];
q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
dbesc($key),
local_channel());
goaway(z_root()."/oauth");
return;
return;
}
if((argc() > 1) && (argv(1) === 'edit' || argv(1) === 'add') && x($_POST,'submit')) {
check_form_security_token_redirectOnErr('oauth', 'oauth');
$name = ((x($_POST,'name')) ? escape_tags($_POST['name']) : '');
$key = ((x($_POST,'key')) ? escape_tags($_POST['key']) : '');
$secret = ((x($_POST,'secret')) ? escape_tags($_POST['secret']) : '');
@@ -48,7 +48,7 @@ class Oauth extends Controller {
$ok = false;
notice( t('Key and Secret are required') . EOL);
}
if($ok) {
if ($_POST['submit']==t("Update")){
$r = q("UPDATE clients SET
@@ -96,13 +96,11 @@ class Oauth extends Controller {
if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('OAuth Apps Manager App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('OAuth authentication tokens for mobile and remote apps');
return $o;
$papp = Apps::get_papp('OAuth Apps Manager');
return Apps::app_render($papp, 'module');
}
if((argc() > 1) && (argv(1) === 'add')) {
$tpl = get_markup_template("oauth_edit.tpl");
$o .= replace_macros($tpl, array(
@@ -118,18 +116,18 @@ class Oauth extends Controller {
));
return $o;
}
if((argc() > 2) && (argv(1) === 'edit')) {
$r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d",
dbesc(argv(2)),
local_channel());
if (!count($r)){
notice(t('Application not found.'));
return;
}
$app = $r[0];
$tpl = get_markup_template("oauth_edit.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth"),
@@ -144,26 +142,26 @@ class Oauth extends Controller {
));
return $o;
}
if((argc() > 2) && (argv(1) === 'delete')) {
check_form_security_token_redirectOnErr('/oauth', 'oauth', 't');
$r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d",
dbesc(argv(2)),
local_channel());
goaway(z_root()."/oauth");
return;
return;
}
$r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my
$r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my
FROM clients
LEFT JOIN tokens ON clients.client_id=tokens.client_id
WHERE clients.uid IN (%d,0)",
local_channel(),
local_channel());
$tpl = get_markup_template("oauth.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth"),
@@ -178,7 +176,7 @@ class Oauth extends Controller {
'$apps' => $r,
));
return $o;
}
}

View File

@@ -16,11 +16,11 @@ class Oauth2 extends Controller {
if(! Apps::system_app_installed(local_channel(), 'OAuth2 Apps Manager'))
return;
if(x($_POST,'remove')){
check_form_security_token_redirectOnErr('oauth2', 'oauth2');
$name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : '');
logger("REMOVE! ".$name." uid: ".local_channel());
logger("REMOVE! ".$name." uid: ".local_channel());
$key = $_POST['remove'];
q("DELETE FROM oauth_authorization_codes WHERE client_id='%s' AND user_id=%d",
dbesc($name),
@@ -35,13 +35,13 @@ class Oauth2 extends Controller {
intval(local_channel())
);
goaway(z_root()."/oauth2");
return;
return;
}
if((argc() > 1) && (argv(1) === 'edit' || argv(1) === 'add') && x($_POST,'submit')) {
check_form_security_token_redirectOnErr('oauth2', 'oauth2');
$name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : '');
$secret = ((x($_POST,'secret')) ? escape_tags(trim($_POST['secret'])) : '');
$redirect = ((x($_POST,'redirect')) ? escape_tags(trim($_POST['redirect'])) : '');
@@ -53,7 +53,7 @@ class Oauth2 extends Controller {
$ok = false;
notice( t('Name and Secret are required') . EOL);
}
if($ok) {
if ($_POST['submit']==t("Update")){
$r = q("UPDATE oauth_clients SET
@@ -61,7 +61,7 @@ class Oauth2 extends Controller {
client_secret = '%s',
redirect_uri = '%s',
grant_types = '%s',
scope = '%s',
scope = '%s',
user_id = %d
WHERE client_id='%s' and user_id = %s",
dbesc($name),
@@ -102,12 +102,10 @@ class Oauth2 extends Controller {
if(! Apps::system_app_installed(local_channel(), 'OAuth2 Apps Manager')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('OAuth2 Apps Manager App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('OAuth2 authenticatication tokens for mobile and remote apps');
return $o;
$papp = Apps::get_papp('OAuth2 Apps Manager');
return Apps::app_render($papp, 'module');
}
if((argc() > 1) && (argv(1) === 'add')) {
$tpl = get_markup_template("oauth2_edit.tpl");
$o .= replace_macros($tpl, array(
@@ -123,20 +121,20 @@ class Oauth2 extends Controller {
));
return $o;
}
if((argc() > 2) && (argv(1) === 'edit')) {
$r = q("SELECT * FROM oauth_clients WHERE client_id='%s' AND user_id= %d",
dbesc(argv(2)),
intval(local_channel())
);
if (! $r){
notice(t('OAuth2 Application not found.'));
return;
}
$app = $r[0];
$tpl = get_markup_template("oauth2_edit.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth2"),
@@ -151,10 +149,10 @@ class Oauth2 extends Controller {
));
return $o;
}
if((argc() > 2) && (argv(1) === 'delete')) {
check_form_security_token_redirectOnErr('oauth2', 'oauth2', 't');
$r = q("DELETE FROM oauth_clients WHERE client_id = '%s' AND user_id = %d",
dbesc(argv(2)),
intval(local_channel())
@@ -172,11 +170,11 @@ class Oauth2 extends Controller {
intval(local_channel())
);
goaway(z_root()."/oauth2");
return;
return;
}
$r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my
$r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my
FROM oauth_clients
LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id AND
oauth_clients.user_id=oauth_access_tokens.user_id
@@ -184,7 +182,7 @@ class Oauth2 extends Controller {
intval(local_channel()),
intval(local_channel())
);
$tpl = get_markup_template("oauth2.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth2"),
@@ -199,7 +197,7 @@ class Oauth2 extends Controller {
'$apps' => $r,
));
return $o;
}
}

View File

@@ -77,8 +77,11 @@ class Oep extends \Zotlabs\Web\Controller {
$res = $matches[2];
}
if(strpos($res,'b64.') === 0) {
$res = base64url_decode(substr($res,4));
$res = unpack_link_id($res);
if ($res === false) {
notice(t('Malformed message id.') . EOL);
return;
}
$item_normal = item_normal();
@@ -122,12 +125,12 @@ class Oep extends \Zotlabs\Web\Controller {
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
"' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') .
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
"' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
if($p[0]['title'])
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
@@ -210,13 +213,13 @@ class Oep extends \Zotlabs\Web\Controller {
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
"' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') .
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
if($p[0]['title'])
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
"' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
if($p[0]['title'])
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
$o .= $x;
@@ -296,14 +299,14 @@ class Oep extends \Zotlabs\Web\Controller {
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
"' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') .
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
if($p[0]['title'])
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
"' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
if($p[0]['title'])
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
$o .= $x;
$o .= "[/share]";
@@ -374,7 +377,7 @@ class Oep extends \Zotlabs\Web\Controller {
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
"' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') .
"' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
if($p[0]['title'])

124
Zotlabs/Module/Outbox.php Normal file
View File

@@ -0,0 +1,124 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Config;
use Zotlabs\Lib\ThreadListener;
use Zotlabs\Web\Controller;
use Zotlabs\Web\HTTPSig;
class Outbox extends Controller {
function init() {
if (ActivityStreams::is_as_request()) {
if (observer_prohibited(true)) {
killme();
}
$channel = channelx_by_nick(argv(1));
if (!$channel) {
killme();
}
if (intval($channel['channel_system'])) {
killme();
}
$sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
$portable_id = $sigdata['portable_id'];
if (!check_channelallowed($portable_id)) {
http_status_exit(403, 'Permission denied');
}
if (!check_siteallowed($sigdata['signer'])) {
http_status_exit(403, 'Permission denied');
}
observer_auth($portable_id);
}
elseif (Config::get('system', 'require_authenticated_fetch', false)) {
http_status_exit(403, 'Permission denied');
}
$observer_hash = get_observer_hash();
$params = [];
$params['begin'] = ((x($_REQUEST, 'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE);
$params['end'] = ((x($_REQUEST, 'date_end')) ? $_REQUEST['date_end'] : '');
$params['type'] = 'json';
$params['pages'] = ((x($_REQUEST, 'pages')) ? intval($_REQUEST['pages']) : 0);
$params['top'] = ((x($_REQUEST, 'top')) ? intval($_REQUEST['top']) : 0);
$params['direction'] = ((x($_REQUEST, 'direction')) ? dbesc($_REQUEST['direction']) : 'desc'); // unimplemented
$params['cat'] = ((x($_REQUEST, 'cat')) ? escape_tags($_REQUEST['cat']) : '');
$params['compat'] = 1;
$total = items_fetch(
[
'total' => true,
'wall' => 1,
'datequery' => $params['end'],
'datequery2' => $params['begin'],
'direction' => dbesc($params['direction']),
'pages' => $params['pages'],
'order' => dbesc('post'),
'top' => $params['top'],
'cat' => $params['cat'],
'compat' => $params['compat']
], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module
);
if ($total) {
App::set_pager_total($total);
App::set_pager_itemspage(30);
}
if (App::$pager['unset'] && $total > 30) {
$ret = Activity::paged_collection_init($total, App::$query_string);
}
else {
$items = items_fetch(
[
'wall' => 1,
'datequery' => $params['end'],
'datequery2' => $params['begin'],
'records' => intval(App::$pager['itemspage']),
'start' => intval(App::$pager['start']),
'direction' => dbesc($params['direction']),
'pages' => $params['pages'],
'order' => dbesc('post'),
'top' => $params['top'],
'cat' => $params['cat'],
'compat' => $params['compat']
], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module
);
if ($items && $observer_hash) {
// check to see if this observer is a connection. If not, register any items
// belonging to this channel for notification of deletion/expiration
$x = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
intval($channel['channel_id']),
dbesc($observer_hash)
);
if (!$x) {
foreach ($items as $item) {
if (strpos($item['mid'], z_root()) === 0) {
ThreadListener::store($item['mid'], $observer_hash);
}
}
}
}
$ret = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', $total);
}
as_return_and_die($ret, $channel);
}
}
}

View File

@@ -32,14 +32,14 @@ class Owa extends Controller {
$keyId = $sigblock['keyId'];
if ($keyId) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
WHERE hubloc_id_url = '%s'",
WHERE hubloc_id_url = '%s' AND xchan_pubkey != '' ",
dbesc($keyId)
);
if (! $r) {
$found = discover_by_webbie(str_replace('acct:','',$keyId));
if ($found) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
WHERE hubloc_id_url = '%s'",
WHERE hubloc_id_url = '%s' AND xchan_pubkey != '' ",
dbesc($keyId)
);
}

View File

@@ -27,10 +27,10 @@ class Pdledit extends Controller {
info( t('Layout updated.') . EOL);
goaway(z_root() . '/pdledit/' . $_REQUEST['module']);
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
@@ -39,10 +39,8 @@ class Pdledit extends Controller {
if(! Apps::system_app_installed(local_channel(), 'PDL Editor')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('PDL Editor App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Provides the ability to edit system page layouts');
return $o;
$papp = Apps::get_papp('PDL Editor');
return Apps::app_render($papp, 'module');
}
if(argc() > 2 && argv(2) === 'reset') {
@@ -68,7 +66,7 @@ class Pdledit extends Controller {
$edited[] = substr(str_replace('.pdl','',$rv['k']),4);
}
}
$files = glob('Zotlabs/Module/*.php');
if($files) {
foreach($files as $f) {
@@ -81,21 +79,21 @@ class Pdledit extends Controller {
}
$o .= '</div>';
// list module pdl files
return $o;
}
$t = get_pconfig(local_channel(),'system',$module);
$s = file_get_contents(theme_include($module));
if(! $t) {
$t = $s;
}
}
if(! $t) {
notice( t('Layout not found.') . EOL);
return '';
}
$o = replace_macros(get_markup_template('pdledit.tpl'),array(
'$header' => t('Edit System Page Description'),
'$mname' => t('Module Name:'),
@@ -107,8 +105,8 @@ class Pdledit extends Controller {
'$content' => htmlspecialchars($t,ENT_COMPAT,'UTF-8'),
'$submit' => t('Submit')
));
return $o;
}
}

View File

@@ -40,16 +40,16 @@ class Permcats extends Controller {
}
}
}
\Zotlabs\Lib\Permcat::update(local_channel(),$name,$pcarr);
Libsync::build_sync_packet();
info( t('Permission category saved.') . EOL);
return;
}
function get() {
@@ -59,16 +59,14 @@ class Permcats extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Permission Categories')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Permission Categories App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Create custom connection permission limits');
return $o;
$papp = Apps::get_papp('Permission Categories');
return Apps::app_render($papp, 'module');
}
$channel = App::get_channel();
if(argc() > 1)
$name = hex2bin(argv(1));
if(argc() > 1)
$name = hex2bin(argv(1));
if(argc() > 2 && argv(2) === 'drop') {
\Zotlabs\Lib\Permcat::delete(local_channel(),$name);
@@ -130,5 +128,5 @@ class Permcats extends Controller {
));
return $o;
}
}

View File

@@ -3,6 +3,12 @@
namespace Zotlabs\Module;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\Config;
require_once('include/security.php');
require_once('include/attach.php');
require_once('include/photo/photo_driver.php');
@@ -11,6 +17,48 @@ class Photo extends \Zotlabs\Web\Controller {
function init() {
if (ActivityStreams::is_as_request()) {
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
$portable_id = $sigdata['portable_id'];
if (! check_channelallowed($portable_id)) {
http_status_exit(403, 'Permission denied');
}
if (! check_siteallowed($sigdata['signer'])) {
http_status_exit(403, 'Permission denied');
}
observer_auth($portable_id);
}
elseif (Config::get('system','require_authenticated_fetch',false)) {
http_status_exit(403,'Permission denied');
}
$observer_xchan = get_observer_hash();
$allowed = false;
$bear = Activity::token_from_request();
if ($bear) {
logger('bear: ' . $bear, LOGGER_DEBUG);
}
$r = q("select * from item where resource_type = 'photo' and resource_id = '%s' limit 1",
dbesc(argv(1))
);
if ($r) {
$allowed = attach_can_view($r[0]['uid'],$observer_xchan,argv(1)/*,$bear*/);
}
if (! $allowed) {
http_status_exit(404,'Permission denied.');
}
$channel = channelx_by_n($r[0]['uid']);
$obj = json_decode($r[0]['obj'],true);
as_return_and_die($obj,$channel);
}
$streaming = null;
$channel = null;
$person = 0;
@@ -33,19 +81,19 @@ class Photo extends \Zotlabs\Web\Controller {
$cache_mode = [ 'on' => false, 'age' => 86400, 'exp' => true, 'leak' => false ];
call_hooks('cache_mode_hook', $cache_mode);
$observer_xchan = get_observer_hash();
$cachecontrol = ', no-cache';
if(isset($type)) {
/**
* Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites.
*
*
*/
$default = get_default_profile_photo();
if($type === 'profile') {
switch($res) {
case 'm':
@@ -62,9 +110,9 @@ class Photo extends \Zotlabs\Web\Controller {
break;
}
}
$uid = $person;
$data = '';
if ($uid > 0) {
@@ -81,13 +129,13 @@ class Photo extends \Zotlabs\Web\Controller {
else
$data = dbunescbin($r[0]['content']);
}
if(! $data) {
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
call_hooks('get_profile_photo',$d);
$resolution = $d['imgscale'];
$uid = $d['channel_id'];
$uid = $d['channel_id'];
$default = $d['default'];
$data = $d['data'];
$mimetype = $d['mimetype'];
@@ -105,11 +153,11 @@ class Photo extends \Zotlabs\Web\Controller {
$cachecontrol .= ', must-revalidate';
}
else {
/**
* Other photos
*/
/* Check for a cookie to indicate display pixel density, in order to detect high-resolution
displays. This procedure was derived from the "Retina Images" by Jeremey Worboys,
used in accordance with the Creative Commons Attribution 3.0 Unported License.
@@ -127,12 +175,12 @@ class Photo extends \Zotlabs\Web\Controller {
// $prvcachecontrol = 'no-cache';
$status = 'no cookie';
}
$resolution = 0;
if(strpos($photo,'.') !== false)
$photo = substr($photo,0,strpos($photo,'.'));
if(substr($photo,-2,1) == '-') {
$resolution = intval(substr($photo,-1,1));
$photo = substr($photo,0,-2);
@@ -140,7 +188,7 @@ class Photo extends \Zotlabs\Web\Controller {
if ($resolution == 2 && ($cookie_value > 1))
$resolution = 1;
}
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
dbesc($photo),
intval($resolution)
@@ -151,7 +199,7 @@ class Photo extends \Zotlabs\Web\Controller {
$u = intval($r[0]['photo_usage']);
if($u) {
$allowed = 1;
if($u === PHOTO_COVER)
if($u === PHOTO_COVER)
if($resolution < PHOTO_RES_COVER_1200)
$allowed = (-1);
if($u === PHOTO_PROFILE)
@@ -184,9 +232,9 @@ class Photo extends \Zotlabs\Web\Controller {
dbesc($photo),
intval($resolution)
);
$exists = (($e) ? true : false);
if($exists && $allowed) {
$expires = strtotime($e[0]['expires'] . 'Z');
$data = dbunescbin($e[0]['content']);
@@ -209,16 +257,16 @@ class Photo extends \Zotlabs\Web\Controller {
}
}
}
}
else
http_status_exit(404,'not found');
}
if(! $data)
killme();
$etag = '"' . md5($data . $modified) . '"';
if($modified == 0)
$modified = time();
@@ -241,39 +289,39 @@ class Photo extends \Zotlabs\Web\Controller {
}
if(isset($prvcachecontrol)) {
// it is a private photo that they have no permission to view.
// tell the browser not to cache it, in case they authenticate
// and subsequently have permission to see it
header("Cache-Control: " . $prvcachecontrol);
}
else {
// The photo cache default is 1 day to provide a privacy trade-off,
// as somebody reducing photo permissions on a photo that is already
// as somebody reducing photo permissions on a photo that is already
// "in the wild" won't be able to stop the photo from being viewed
// for this amount amount of time once it is in the browser cache.
// The privacy expectations of your site members and their perception
// The privacy expectations of your site members and their perception
// of privacy where it affects the entire project may be affected.
// This has performance considerations but we highly recommend you
// leave it alone.
// This has performance considerations but we highly recommend you
// leave it alone.
$maxage = $cache_mode['age'];
if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time()))
$expires = time() + $maxage;
else
$maxage = $expires - time();
header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT");
// set CDN/Infrastructure caching much lower than maxage
// 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);
}
header("Content-type: " . $mimetype);
@@ -281,7 +329,7 @@ class Photo extends \Zotlabs\Web\Controller {
header("ETag: " . $etag);
header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data)));
// If it's a file resource, stream it.
// If it's a file resource, stream it.
if($streaming) {
if(strpos($streaming,'store') !== false)
$istream = fopen($streaming,'rb');
@@ -300,5 +348,5 @@ class Photo extends \Zotlabs\Web\Controller {
killme();
}
}

View File

@@ -171,6 +171,7 @@ class Photos extends \Zotlabs\Web\Controller {
}
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
}
if((argc() > 2) && (x($_REQUEST,'delete')) && ($_REQUEST['delete'] === t('Delete Photo'))) {
@@ -501,6 +502,9 @@ class Photos extends \Zotlabs\Web\Controller {
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
}
if(is_ajax())
killme();
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $r['data']['folder']);
}
@@ -709,13 +713,15 @@ class Photos extends \Zotlabs\Web\Controller {
]);
if($x = photos_album_exists($owner_uid, get_observer_hash(), $datum)) {
\App::set_pager_itemspage(30);
$album = $x['display_path'];
}
else {
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
$album = '/';
//goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
}
\App::set_pager_itemspage(30);
if($_GET['order'] === 'posted')
$order = 'ASC';
else
@@ -876,7 +882,7 @@ class Photos extends \Zotlabs\Web\Controller {
$prevlink = '';
$nextlink = '';
if($_GET['order'] === 'posted')
if(isset($_GET['order']) && $_GET['order'] === 'posted')
$order = 'ASC';
else
$order = 'DESC';
@@ -901,8 +907,8 @@ class Photos extends \Zotlabs\Web\Controller {
}
}
$prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
$nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
$prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['hash'] . (($order == 'ASC') ? '?f=&order=posted' : '');
$nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['hash'] . (($order == 'ASC') ? '?f=&order=posted' : '');
}
@@ -987,7 +993,7 @@ class Photos extends \Zotlabs\Web\Controller {
}
$tags = array();
if($link_item['term']) {
if(x($link_item, 'term')) {
$cnt = 0;
foreach($link_item['term'] as $t) {
$tags[$cnt] = array(0 => format_term_for_display($t));
@@ -1178,10 +1184,8 @@ class Photos extends \Zotlabs\Web\Controller {
if($observer['xchan_hash'] === $item['author_xchan'] || $observer['xchan_hash'] === $item['owner_xchan'])
$drop = replace_macros(get_markup_template('photo_drop.tpl'), array('$id' => $item['id'], '$delete' => t('Delete')));
$name_e = $profile_name;
$title_e = $item['title'];
unobscure($item);
$body_e = prepare_text($item['body'],$item['mimetype']);
$comments .= replace_macros($template,array(

View File

@@ -37,7 +37,7 @@ class Pin extends \Zotlabs\Web\Controller {
http_status_exit(404, 'Not found');
}
$midb64 = 'b64.' . base64url_encode($r[0]['mid']);
$midb64 = gen_link_id($r[0]['mid']);
$pinned = (in_array($midb64, get_pconfig($r[0]['uid'], 'pinned', $r[0]['item_type'], [])) ? true : false);
switch(argv(1)) {

View File

@@ -1,707 +0,0 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Lib\Apps;
require_once('include/bbcode.php');
/**
* @brief Ping Controller.
*
*/
class Ping extends \Zotlabs\Web\Controller {
/**
* @brief do several updates when pinged.
*
* This function does several tasks. Whenever called it checks for new messages,
* introductions, notifications, etc. and returns a json with the results.
*
* @result JSON
*/
function init() {
$result = array();
$notifs = array();
$result['notify'] = 0;
$result['home'] = 0;
$result['network'] = 0;
$result['intros'] = 0;
$result['mail'] = 0;
$result['register'] = 0;
$result['events'] = 0;
$result['events_today'] = 0;
$result['birthdays'] = 0;
$result['birthdays_today'] = 0;
$result['all_events'] = 0;
$result['all_events_today'] = 0;
$result['notice'] = [];
$result['info'] = [];
$result['pubs'] = 0;
$result['files'] = 0;
$result['forums'] = 0;
$result['forums_sub'] = [];
if(! $_SESSION['static_loadtime'])
$_SESSION['static_loadtime'] = datetime_convert();
$t0 = dba_timer();
header("content-type: application/json");
$vnotify = false;
$item_normal = item_normal();
if(local_channel()) {
$vnotify = get_pconfig(local_channel(),'system','vnotify');
$evdays = intval(get_pconfig(local_channel(),'system','evdays'));
$ob_hash = get_observer_hash();
}
// if unset show all visual notification types
if($vnotify === false)
$vnotify = (-1);
if($evdays < 1)
$evdays = 3;
/**
* If you have several windows open to this site and switch to a different channel
* in one of them, the others may get into a confused state showing you a page or options
* on that page which were only valid under the old identity. You session has changed.
* Therefore we send a notification of this fact back to the browser where it is picked up
* in javascript and which reloads the page it is on so that it is valid under the context
* of the now current channel.
*/
$result['invalid'] = ((intval($_GET['uid'])) && (intval($_GET['uid']) != local_channel()) ? 1 : 0);
/**
* Send all system messages (alerts) to the browser.
* Some are marked as informational and some represent
* errors or serious notifications. These typically
* will popup on the current page (no matter what page it is)
*/
if(x($_SESSION, 'sysmsg')){
foreach ($_SESSION['sysmsg'] as $m){
$result['notice'][] = array('message' => $m);
}
unset($_SESSION['sysmsg']);
}
if(x($_SESSION, 'sysmsg_info')){
foreach ($_SESSION['sysmsg_info'] as $m){
$result['info'][] = array('message' => $m);
}
unset($_SESSION['sysmsg_info']);
}
if(! ($vnotify & VNOTIFY_INFO))
$result['info'] = array();
if(! ($vnotify & VNOTIFY_ALERT))
$result['notice'] = array();
if(\App::$install) {
echo json_encode($result);
killme();
}
/**
* Update chat presence indication (if applicable)
*/
if(get_observer_hash() && (! $result['invalid'])) {
$r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
dbesc(get_observer_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(get_observer_hash()),
dbesc(datetime_convert()),
dbesc('online'),
dbesc($_SERVER['REMOTE_ADDR'])
);
}
}
/**
* Chatpresence continued... 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')
);
$sql_extra = '';
if(! ($vnotify & VNOTIFY_LIKE))
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
if(local_channel()) {
$notify_pubs = ($vnotify & VNOTIFY_PUBS) && can_view_public_stream() && Apps::system_app_installed(local_channel(), 'Public Stream');
}
else {
$notify_pubs = can_view_public_stream();
}
if($notify_pubs) {
$sys = get_sys_channel();
$pubs = q("SELECT count(id) as total from item
WHERE uid = %d
AND item_unseen = 1
AND author_xchan != '%s'
AND created > '" . datetime_convert('UTC','UTC',$_SESSION['static_loadtime']) . "'
$item_normal
$sql_extra",
intval($sys['channel_id']),
dbesc(get_observer_hash())
);
if($pubs)
$result['pubs'] = intval($pubs[0]['total']);
}
if((argc() > 1) && (argv(1) === 'pubs') && ($notify_pubs)) {
$sys = get_sys_channel();
$result = array();
$r = q("SELECT * FROM item
WHERE uid = %d
AND item_unseen = 1
AND author_xchan != '%s'
AND created > '" . datetime_convert('UTC','UTC',$_SESSION['static_loadtime']) . "'
$item_normal
$sql_extra
ORDER BY created DESC
LIMIT 300",
intval($sys['channel_id']),
dbesc(get_observer_hash())
);
if($r) {
xchan_query($r);
foreach($r as $rr) {
$rr['llink'] = str_replace('display/', 'pubstream/?f=&mid=', $rr['llink']);
$result[] = \Zotlabs\Lib\Enotify::format($rr);
}
}
// logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA);
echo json_encode(array('notify' => $result));
killme();
}
$t1 = dba_timer();
if((! local_channel()) || ($result['invalid'])) {
echo json_encode($result);
killme();
}
/**
* Everything following is only permitted under the context of a locally authenticated site member.
*/
/**
* Handle "mark all xyz notifications read" requests.
*/
// mark all items read
if(x($_REQUEST, 'markRead') && local_channel()) {
switch($_REQUEST['markRead']) {
case 'network':
$r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1",
intval(local_channel())
);
break;
case 'home':
$r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_wall = 1",
intval(local_channel())
);
break;
case 'mail':
$r = q("UPDATE mail SET mail_seen = 1 WHERE channel_id = %d AND mail_seen = 0",
intval(local_channel())
);
break;
case 'all_events':
$r = q("UPDATE event SET dismissed = 1 WHERE uid = %d AND dismissed = 0 AND dtstart < '%s' AND dtstart > '%s' ",
intval(local_channel()),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
);
break;
case 'notify':
$r = q("update notify set seen = 1 where uid = %d",
intval(local_channel())
);
break;
case 'pubs':
unset($_SESSION['static_loadtime']);
break;
default:
break;
}
}
if(x($_REQUEST, 'markItemRead') && local_channel()) {
$r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND parent = %d",
intval(local_channel()),
intval($_REQUEST['markItemRead'])
);
}
/**
* URL ping/something will return detail for "something", e.g. a json list with which to populate a notification
* dropdown menu.
*/
if(argc() > 1 && argv(1) === 'notify') {
$t = q("SELECT * FROM notify WHERE uid = %d AND seen = 0 ORDER BY CREATED DESC",
intval(local_channel())
);
if($t) {
foreach($t as $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']);
$mid = ((strpos($mid, 'b64.') === 0) ? @base64url_decode(substr($mid, 4)) : $mid);
if(in_array($tt['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
// we need the thread parent
$r = q("select thr_parent from item where mid = '%s' and uid = %d limit 1",
dbesc($mid),
intval(local_channel())
);
$b64mid = ((strpos($r[0]['thr_parent'], 'b64.') === 0) ? $r[0]['thr_parent'] : 'b64.' . base64url_encode($r[0]['thr_parent']));
}
else {
$b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : 'b64.' . base64url_encode($mid));
}
$notifs[] = array(
'notify_link' => z_root() . '/notify/view/' . $tt['id'],
'name' => $tt['xname'],
'url' => $tt['url'],
'photo' => $tt['photo'],
'when' => relative_date($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
);
}
}
echo json_encode(array('notify' => $notifs));
killme();
}
if(argc() > 1 && argv(1) === 'mail') {
$channel = \App::get_channel();
$t = 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 limit 50",
intval(local_channel()),
dbesc($channel['channel_hash'])
);
if($t) {
foreach($t as $zz) {
$notifs[] = array(
'notify_link' => z_root() . '/mail/' . $zz['id'],
'name' => $zz['xchan_name'],
'addr' => $zz['xchan_addr'],
'url' => $zz['xchan_url'],
'photo' => $zz['xchan_photo_s'],
'when' => relative_date($zz['created']),
'hclass' => (intval($zz['mail_seen']) ? 'notify-seen' : 'notify-unseen'),
'message' => t('sent you a private message'),
);
}
}
echo json_encode(array('notify' => $notifs));
killme();
}
if(argc() > 1 && (argv(1) === 'network' || argv(1) === 'home')) {
$result = array();
if(argv(1) === 'home') {
$sql_extra .= ' and item_wall = 1 ';
}
$r = q("SELECT * FROM item
WHERE uid = %d
AND item_unseen = 1
AND author_xchan != '%s'
$item_normal
$sql_extra
ORDER BY created DESC
LIMIT 300",
intval(local_channel()),
dbesc($ob_hash)
);
if($r) {
xchan_query($r);
foreach($r as $item) {
$result[] = \Zotlabs\Lib\Enotify::format($item);
}
}
// logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA);
echo json_encode(array('notify' => $result));
killme();
}
if(argc() > 1 && (argv(1) === 'intros')) {
$result = array();
$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(local_channel())
);
if($r) {
foreach($r as $rr) {
$result[] = array(
'notify_link' => z_root() . '/connections/ifpending',
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'],
'photo' => $rr['xchan_photo_s'],
'when' => relative_date($rr['abook_created']),
'hclass' => ('notify-unseen'),
'message' => t('added your channel')
);
}
}
logger('ping (intros): ' . print_r($result, true), LOGGER_DATA);
echo json_encode(array('notify' => $result));
killme();
}
if((argc() > 1 && (argv(1) === 'register')) && is_site_admin()) {
$result = array();
$r = q("SELECT account_email, account_created from account where (account_flags & %d) > 0",
intval(ACCOUNT_PENDING)
);
if($r) {
foreach($r as $rr) {
$result[] = array(
'notify_link' => z_root() . '/admin/accounts',
'name' => $rr['account_email'],
'addr' => $rr['account_email'],
'url' => '',
'photo' => z_root() . '/' . get_default_profile_photo(48),
'when' => relative_date($rr['account_created']),
'hclass' => ('notify-unseen'),
'message' => t('requires approval')
);
}
}
logger('ping (register): ' . print_r($result, true), LOGGER_DATA);
echo json_encode(array('notify' => $result));
killme();
}
if(argc() > 1 && (argv(1) === 'all_events')) {
$bd_format = t('g A l F d') ; // 8 AM Friday January 18
$result = array();
$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 LIMIT 1000",
intval(local_channel()),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
);
if($r) {
foreach($r as $rr) {
$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]') : '');
$result[] = array(
'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')
);
}
}
logger('ping (all_events): ' . print_r($result, true), LOGGER_DATA);
echo json_encode(array('notify' => $result));
killme();
}
if(argc() > 1 && (argv(1) === 'files')) {
$result = array();
$r = q("SELECT item.created, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM item
LEFT JOIN xchan on author_xchan = xchan_hash
WHERE item.verb = '%s'
AND item.obj_type = '%s'
AND item.uid = %d
AND item.owner_xchan != '%s'
AND item.item_unseen = 1",
dbesc(ACTIVITY_POST),
dbesc(ACTIVITY_OBJ_FILE),
intval(local_channel()),
dbesc($ob_hash)
);
if($r) {
foreach($r as $rr) {
$result[] = array(
'notify_link' => z_root() . '/sharedwithme',
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'],
'photo' => $rr['xchan_photo_s'],
'when' => relative_date($rr['created']),
'hclass' => ('notify-unseen'),
'message' => t('shared a file with you')
);
}
}
logger('ping (files): ' . print_r($result, true), LOGGER_DATA);
echo json_encode(array('notify' => $result));
killme();
}
/**
* Normal ping - just the counts, no detail
*/
if($vnotify & VNOTIFY_SYSTEM) {
$t = q("select count(*) as total from notify where uid = %d and seen = 0",
intval(local_channel())
);
if($t)
$result['notify'] = intval($t[0]['total']);
}
$t2 = dba_timer();
if($vnotify & VNOTIFY_FILES) {
$files = q("SELECT count(id) as total 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(local_channel()),
dbesc($ob_hash)
);
if($files)
$result['files'] = intval($files[0]['total']);
}
$t3 = dba_timer();
if($vnotify & (VNOTIFY_NETWORK|VNOTIFY_CHANNEL)) {
$r = q("SELECT id, item_wall FROM item
WHERE uid = %d and item_unseen = 1
$item_normal
$sql_extra
AND author_xchan != '%s'",
intval(local_channel()),
dbesc($ob_hash)
);
if($r) {
$arr = array('items' => $r);
call_hooks('network_ping', $arr);
foreach ($r as $it) {
if(intval($it['item_wall']))
$result['home'] ++;
else
$result['network'] ++;
}
}
}
if(! ($vnotify & VNOTIFY_NETWORK))
$result['network'] = 0;
if(! ($vnotify & VNOTIFY_CHANNEL))
$result['home'] = 0;
$t4 = dba_timer();
if($vnotify & VNOTIFY_INTRO) {
$intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
intval(local_channel())
);
$t5 = dba_timer();
if($intr)
$result['intros'] = intval($intr[0]['total']);
}
$t6 = dba_timer();
$channel = \App::get_channel();
if($vnotify & VNOTIFY_MAIL) {
$mails = q("SELECT count(id) as total from mail
WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
intval(local_channel()),
dbesc($channel['channel_hash'])
);
if($mails)
$result['mail'] = intval($mails[0]['total']);
}
if($vnotify & VNOTIFY_REGISTER) {
if (\App::$config['system']['register_policy'] == REGISTER_APPROVE && is_site_admin()) {
$regs = q("SELECT count(account_id) as total from account where (account_flags & %d) > 0",
intval(ACCOUNT_PENDING)
);
if($regs)
$result['register'] = intval($regs[0]['total']);
}
}
$t7 = dba_timer();
if($vnotify & (VNOTIFY_EVENT|VNOTIFY_EVENTTODAY|VNOTIFY_BIRTHDAY)) {
$events = q("SELECT etype, dtstart, adjust FROM event
WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
and etype in ( 'event', 'birthday' )
ORDER BY dtstart ASC ",
intval(local_channel()),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
);
if($events) {
$result['all_events'] = count($events);
if($result['all_events']) {
$str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d');
foreach($events as $x) {
$bd = false;
if($x['etype'] === 'birthday') {
$result['birthdays'] ++;
$bd = true;
}
else {
$result['events'] ++;
}
if(datetime_convert('UTC', ((intval($x['adjust'])) ? date_default_timezone_get() : 'UTC'), $x['dtstart'], 'Y-m-d') === $str_now) {
$result['all_events_today'] ++;
if($bd)
$result['birthdays_today'] ++;
else
$result['events_today'] ++;
}
}
}
}
}
if(! ($vnotify & VNOTIFY_EVENT))
$result['all_events'] = $result['events'] = 0;
if(! ($vnotify & VNOTIFY_EVENTTODAY))
$result['all_events_today'] = $result['events_today'] = 0;
if(! ($vnotify & VNOTIFY_BIRTHDAY))
$result['birthdays'] = 0;
if($vnotify & VNOTIFY_FORUMS) {
$forums = get_forum_channels(local_channel());
if($forums) {
$item_normal = item_normal();
$fcount = count($forums);
$forums['total'] = 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(local_channel()),
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 count(id) as unseen from item
where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $item_normal $sql_extra",
intval(local_channel()),
dbesc($forums[$x]['xchan_hash']),
dbesc($forums[$x]['xchan_hash'])
);
if($r[0]['unseen']) {
$forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/network/?f=&pf=1&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'] = $r[0]['unseen'];
$forums[$x]['private_forum'] = (($forums[$x]['private_forum']) ? 'lock' : '');
$forums[$x]['message'] = (($forums[$x]['private_forum']) ? t('Private forum') : t('Public forum'));
$forums['total'] = $forums['total'] + $r[0]['unseen'];
unset($forums[$x]['abook_id']);
unset($forums[$x]['xchan_hash']);
unset($forums[$x]['xchan_name']);
unset($forums[$x]['xchan_url']);
unset($forums[$x]['xchan_photo_s']);
//if($forums[$x]['private_forum'])
// unset($forums[$x]['private_forum']);
}
else {
unset($forums[$x]);
}
}
$result['forums'] = $forums['total'];
unset($forums['total']);
$result['forums_sub'] = $forums;
}
}
$x = json_encode($result);
$t8 = dba_timer();
// logger('ping timer: ' . sprintf('%01.4f %01.4f %01.4f %01.4f %01.4f %01.4f %01.4f %01.4f',$t8 - $t7, $t7 - $t6, $t6 - $t5, $t5 - $t4, $t4 - $t3, $t3 - $t2, $t2 - $t1, $t1 - $t0));
echo $x;
killme();
}
}

View File

@@ -9,11 +9,11 @@ use Zotlabs\Web\Controller;
*
* Poke, prod, finger, or otherwise do unspeakable things to somebody - who must be a connection in your address book
* This function can be invoked with the required arguments (verb and cid and private and possibly parent) silently via ajax or
* other web request. You must be logged in and connected to a channel.
* other web request. You must be logged in and connected to a channel.
* If the required arguments aren't present, we'll display a simple form to choose a recipient and a verb.
* parent is a special argument which let's you attach this activity as a comment to an existing conversation, which
* may have started with somebody else poking (etc.) somebody, but this isn't necessary. This can be used in the adult
* plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
* plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
*
* private creates a private conversation with the recipient. Otherwise your channel's default post privacy is used.
*
@@ -25,41 +25,41 @@ require_once('include/items.php');
class Poke extends Controller {
function init() {
if(! local_channel())
return;
if(! Apps::system_app_installed(local_channel(), 'Poke')) {
return;
}
$uid = local_channel();
$channel = App::get_channel();
$verb = notags(trim($_REQUEST['verb']));
if(! $verb)
if(! $verb)
return;
$verbs = get_poke_verbs();
if(! array_key_exists($verb,$verbs))
return;
$activity = ACTIVITY_POKE . '#' . urlencode($verbs[$verb][0]);
$contact_id = intval($_REQUEST['cid']);
$xchan = trim($_REQUEST['xchan']);
if(! ($contact_id || $xchan))
return;
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
logger('poke: verb ' . $verb . ' contact ' . $contact_id, LOGGER_DEBUG);
if($contact_id) {
$r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where abook_id = %d and abook_channel = %d LIMIT 1",
intval($contact_id),
@@ -71,17 +71,17 @@ class Poke extends Controller {
dbesc($xchan . '%')
);
}
if(! $r) {
logger('poke: no target.');
return;
}
$target = $r[0];
$parent_item = null;
if($parent) {
$r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid
$r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid
from item where id = %d and parent = %d and uid = %d limit 1",
intval($parent),
intval($parent),
@@ -98,18 +98,18 @@ class Poke extends Controller {
}
}
elseif($contact_id) {
$item_private = ((x($_GET,'private')) ? intval($_GET['private']) : 0);
$allow_cid = (($item_private) ? '<' . $target['abook_xchan']. '>' : $channel['channel_allow_cid']);
$allow_gid = (($item_private) ? '' : $channel['channel_allow_gid']);
$deny_cid = (($item_private) ? '' : $channel['channel_deny_cid']);
$deny_gid = (($item_private) ? '' : $channel['channel_deny_gid']);
}
$arr = array();
$arr['item_wall'] = 1;
@@ -124,7 +124,7 @@ class Poke extends Controller {
$arr['item_private'] = $item_private;
$arr['obj_type'] = ACTIVITY_OBJ_PERSON;
$arr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t($verbs[$verb][0]) . ' ' . '[zrl=' . $target['xchan_url'] . ']' . $target['xchan_name'] . '[/zrl]';
$obj = array(
'type' => ACTIVITY_OBJ_PERSON,
'title' => $target['xchan_name'],
@@ -134,25 +134,25 @@ class Poke extends Controller {
array('rel' => 'photo', 'type' => $target['xchan_photo_mimetype'], 'href' => $target['xchan_photo_l'])
),
);
$arr['obj'] = json_encode($obj);
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
$arr['item_unseen'] = 1;
if(! $parent_item)
$item['item_thread_top'] = 1;
post_activity_item($arr);
return;
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
@@ -161,19 +161,17 @@ class Poke extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Poke')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$o = '<b>' . t('Poke App') . ' (' . t('Not Installed') . '):</b><br>';
$o .= t('Poke somebody in your addressbook');
return $o;
$papp = Apps::get_papp('Poke');
return Apps::app_render($papp, 'module');
}
nav_set_selected('Poke');
$name = '';
$id = '';
if(intval($_REQUEST['c'])) {
$r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash
$r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash
where abook_id = %d and abook_channel = %d limit 1",
intval($_REQUEST['c']),
intval(local_channel())
@@ -183,17 +181,17 @@ class Poke extends Controller {
$id = $r[0]['abook_id'];
}
}
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : '0');
$verbs = get_poke_verbs();
$shortlist = array();
foreach($verbs as $k => $v)
if($v[1] !== 'NOTRANSLATION')
$shortlist[] = array($k,$v[1]);
$poke_basic = get_config('system','poke_basic');
if($poke_basic) {
$title = t('Poke');
@@ -203,7 +201,7 @@ class Poke extends Controller {
$title = t('Poke/Prod');
$desc = t('Poke, prod or do other things to somebody');
}
$o = replace_macros(get_markup_template('poke_content.tpl'),array(
'$title' => $title,
'$poke_basic' => $poke_basic,
@@ -218,8 +216,8 @@ class Poke extends Controller {
'$name' => $name,
'$id' => $id
));
return $o;
}
}

View File

@@ -1,34 +0,0 @@
<?php
/**
* @file Zotlabs/Module/Post.php
*
* @brief Zot endpoint.
*
*/
namespace Zotlabs\Module;
require_once('include/zot.php');
/**
* @brief Post module.
*
*/
class Post extends \Zotlabs\Web\Controller {
function init() {
if(array_key_exists('auth', $_REQUEST)) {
$x = new \Zotlabs\Zot\Auth($_REQUEST);
exit;
}
}
function post() {
if(array_key_exists('data',$_REQUEST)) {
$z = new \Zotlabs\Zot\Receiver($_REQUEST['data'], get_config('system', 'prvkey'), new \Zotlabs\Zot\ZotHandler());
exit;
}
}
}

Some files were not shown because too many files have changed in this diff Show More