Compare commits

..

906 Commits
1.6 ... 1.12

Author SHA1 Message Date
redmatrix
8aee932525 version 2016-08-23 00:46:22 -07:00
redmatrix
8b737e9610 Merge branch 'master' into 1.12RC 2016-08-22 23:02:38 -07:00
redmatrix
0b16a5531a Revert "Merge branch '1.12RC'"
This reverts commit b89c869e7c, reversing
changes made to fbb357ac47.
2016-08-22 20:31:31 -07:00
redmatrix
b7fbd0ee50 Revert "missing release file"
This reverts commit 17fa2d8801.
2016-08-22 20:30:39 -07:00
redmatrix
2afdb7854b Revert "more missing files from merge"
This reverts commit 1bd784cf12.
2016-08-22 20:30:17 -07:00
redmatrix
1bd784cf12 more missing files from merge 2016-08-22 20:19:31 -07:00
redmatrix
17fa2d8801 missing release file 2016-08-22 20:17:37 -07:00
redmatrix
b89c869e7c Merge branch '1.12RC' 2016-08-22 20:05:25 -07:00
redmatrix
1a506ad49c Merge branch '1.12RC' of https://github.com/redmatrix/hubzilla into 1.12RC_merge 2016-08-22 17:06:56 -07:00
redmatrix
b0d3c17f19 public forum fallback checking (when custom/expert permissions are applied) was looking at owner rather than observer perms 2016-08-22 17:06:40 -07:00
jeroenpraat
f4507d878d Spanish and Dutch strings 2016-08-22 19:45:46 +02:00
redmatrix
d4ef3c183c Merge branch '1.12RC' of https://github.com/redmatrix/hubzilla into 1.12RC_merge 2016-08-21 16:29:41 -07:00
redmatrix
5c3b06b8a9 issue #496 2016-08-21 16:29:16 -07:00
jeroenpraat
15d9bf4ebe Updating Spanish and Dutch strings 2016-08-17 17:37:21 +02:00
hubzilla
6dd4e9ac60 Merge pull request #493 from phellmes/de20160817
Update DE translation strings
2016-08-17 20:44:05 +10:00
phellmes
2b0c2891e3 Update DE translation strings 2016-08-17 10:39:21 +02:00
redmatrix
fbb357ac47 Use double quotes for strings passed via templates to javascript. Some translated strings have unescaped single quotes. 2016-08-15 17:20:40 -07:00
redmatrix
38de583db0 Use double quotes for strings passed via templates to javascript. Some translated strings have unescaped single quotes. 2016-08-15 17:20:29 -07:00
redmatrix
055ee75302 Merge branch '1.12RC' of https://github.com/redmatrix/hubzilla into 1.12RC_merge 2016-08-15 13:19:34 -07:00
Einer von Vielen
f95011a565 Merge dev with last changes of homeinstall script in master 2016-08-15 13:19:20 -07:00
Mario Vavti
6bb5ea7a81 Merge branch '1.12RC' of https://github.com/redmatrix/hubzilla into 1.12RC 2016-08-15 11:22:20 +02:00
Mario Vavti
efcde8f3dd update bootstrap 3.3.5 > 3.3.7 2016-08-15 11:21:57 +02:00
Mario Vavti
057266653b fix javascript error if not logged in 2016-08-15 11:20:51 +02:00
Mario Vavti
2755c74c29 btn/dropdown rendering issue 2016-08-14 11:31:44 +02:00
hubzilla
5ad5afe63b Merge pull request #481 from anaqreon/issue-475
Fixed bug preventing images in root photo album from loading in embed…
2016-08-14 09:54:12 +10:00
Mario Vavti
2c3843ee4c remove js debugging 2016-08-13 22:28:40 +02:00
Mario Vavti
e5d1dd111e fix #480, enable bbcode autocomplete for photo comments and remove some redundant javascript 2016-08-13 22:20:54 +02:00
Andrew Manning
125713e938 Fix for older photos not being embedded by the embedphotos tool. 2016-08-13 14:38:13 -04:00
Andrew Manning
e128ff4e8f Fixed bug preventing images in root photo album from loading in embedphotos dialog. 2016-08-13 14:20:41 -04:00
redmatrix
2c8a82713e pending flag not being reset when using autoperms from custom role 2016-08-12 18:18:35 -07:00
zottel
7d2a17ea6e fix auto-connect setting 2016-08-12 14:44:48 -07:00
Mario Vavti
91b8c769bd possible quickfix for multi-acl not honoring jotnets 2016-08-12 14:44:47 -07:00
redmatrix
0637a71669 embed filter adjustments 2016-08-11 17:34:05 -07:00
redmatrix
45dc995967 forum detection was off for forums with custom perms 2016-08-10 20:50:32 -07:00
redmatrix
d8240a40b7 update CHANGELOG for 1.12 2016-08-10 17:35:07 -07:00
redmatrix
adf34fb201 update version 2016-08-10 16:54:57 -07:00
Mario Vavti
82e867a9a8 implement acl for folder creation 2016-08-10 16:17:09 +02:00
redmatrix
7a557d31e0 open editor or comment window when linkdropping to a closed window. We probably also need this for filedropping. 2016-08-10 01:35:58 -07:00
redmatrix
de12503fad allow dropping links on comments as well as posts 2016-08-09 22:52:14 -07:00
redmatrix
5238a27ab3 function order reversed 2016-08-09 20:50:33 -07:00
redmatrix
12162f53b4 You can drag links to the editor (which will be parsed and inserted); as well as files (which will be uploaded) 2016-08-09 18:13:54 -07:00
redmatrix
ec3ca11d0d bad code format 2016-08-09 16:59:35 -07:00
redmatrix
07dca90352 updates to hcard parsing 2016-08-07 21:00:23 -07:00
redmatrix
3338f3c5b2 diaspora vcard updates 2016-08-07 20:16:14 -07:00
redmatrix
de455e4cd0 server roles 2016-08-07 17:40:56 -07:00
redmatrix
5243dd153b use config system.server_role and deprecate 'UNO' 2016-08-07 17:29:35 -07:00
redmatrix
e1659b0725 fix cloud path 2016-08-07 16:21:51 -07:00
Mario Vavti
89c026924b fix /cloud upload for images 2016-08-06 14:40:23 +02:00
Mario Vavti
4f0b138692 bring back acl for cloud file uploads 2016-08-06 12:46:10 +02:00
redmatrix
b6db0f72f5 strings update 2016-08-05 15:40:20 -07:00
redmatrix
9068ae68ad Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-08-05 15:40:10 -07:00
hubzilla
1bff63bd2e Merge pull request #477 from git-marijus/dev
Some work to make multiple acl forms per page work
2016-08-06 07:50:21 +10:00
Mario Vavti
531baa8fc4 Revert "Revert "remove some logging""
This reverts commit e67f5bc6bb.
2016-08-05 16:05:21 +02:00
Mario Vavti
e67f5bc6bb Revert "remove some logging"
This reverts commit 316b090433.
2016-08-05 15:19:17 +02:00
Mario Vavti
316b090433 remove some logging 2016-08-05 14:53:46 +02:00
Mario Vavti
b2298d44a4 multi acl: port /settings 2016-08-05 14:45:06 +02:00
Mario Vavti
c029839971 multi acl: port /display 2016-08-05 14:25:37 +02:00
Mario Vavti
e7e73e6fd1 multi acl: port /thing 2016-08-05 13:37:47 +02:00
Mario Vavti
bed0a5773f multi acl: port /rpost 2016-08-05 13:20:03 +02:00
Mario Vavti
53a2262fef Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-08-05 12:13:50 +02:00
hubzilla
709206accd Merge pull request #476 from anaqreon/wiki
Wiki bbcode parsing
2016-08-05 18:03:31 +10:00
redmatrix
eeabf514ea minor cleanup on ratings - no real functional changes at this time 2016-08-04 18:56:05 -07:00
Andrew Manning
faf1045ef5 Merge remote-tracking branch 'upstream/dev' into wiki 2016-08-04 19:48:59 -04:00
Andrew Manning
6a82ff871f Parse bbcode when page loads 2016-08-04 19:45:35 -04:00
Mario Vavti
7e5428c697 multi acl: provide a acl-form-trigger class which comes handy in certain situations 2016-08-04 21:26:30 +02:00
Mario Vavti
036b72757c multi acl: port /wiki 2016-08-04 12:09:06 +02:00
Mario Vavti
120e9a1e4c multi acl: port /webpages and /mitem 2016-08-04 11:23:43 +02:00
Mario Vavti
b49cfb2efd multi acl: port /chat 2016-08-04 10:46:50 +02:00
Mario Vavti
0340160ba7 multi acl: port /cloud and /filestorage 2016-08-04 10:36:45 +02:00
Mario Vavti
4ede3fd771 multi acl: port photos 2016-08-04 09:10:21 +02:00
Mario Vavti
3783c1af3e Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-08-04 08:10:13 +02:00
redmatrix
51c610de73 issue #474 2016-08-03 21:43:19 -07:00
redmatrix
92862f93f3 issue #474 2016-08-03 21:42:41 -07:00
Andrew Manning
05a9f0aa14 Convert select bbcode tags including [observer], [baseurl], [sitename] 2016-08-03 20:53:51 -04:00
redmatrix
64810405ef Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-08-03 16:12:17 -07:00
redmatrix
382ce4cc61 issue #473 - unable to delete privacy groups 2016-08-03 16:11:15 -07:00
redmatrix
178c983871 issue #473 - unable to delete privacy groups 2016-08-03 16:10:28 -07:00
Mario Vavti
908e15bc90 multi acl: port events 2016-08-03 23:57:41 +02:00
Mario Vavti
df27a48e72 multiple acl: store new data in update_view() 2016-08-03 22:50:37 +02:00
Mario Vavti
b959641ca8 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-08-03 21:17:08 +02:00
Mario Vavti
c50bfa07ca multiple acl work 2016-08-03 21:16:57 +02:00
jeroenpraat
416adeb169 belongs to previous commit 2016-08-03 16:41:36 +02:00
jeroenpraat
61f591cc88 Improved a few schemas - context help fix - dark schemas now have dark text areas (et al.) 2016-08-03 16:33:12 +02:00
redmatrix
8f2106da2b Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-08-02 19:33:09 -07:00
redmatrix
1e988b1fea missing comma in atoken update sql 2016-08-02 19:32:39 -07:00
redmatrix
0febfce268 missing comma in atoken update sql 2016-08-02 19:31:31 -07:00
redmatrix
c4fd0af16d comment policy permissions typo 2016-08-02 18:21:43 -07:00
redmatrix
69354e808f this should sort out likes showing up as wall-to-wall posts on diaspora 2016-08-01 22:12:44 -07:00
redmatrix
3a7d3e3a54 This checkin should make all permission modes work correctly with atokens (they should be able to post content if allowed to). It also removes the strict linkage between permissions and connections so any individual permission can be set for any xchan; even those for which you have no connections. 2016-08-01 20:12:52 -07:00
redmatrix
4c76b31684 /storeurl/cloudurl/ 2016-08-01 17:44:21 -07:00
redmatrix
3d0c90cbc5 allow individual permissions on atokens 2016-07-31 23:17:07 -07:00
redmatrix
9b9621e10d add a few more path macros to portable menu elements (channelurl, pageurl, storeurl and baseurl) 2016-07-31 20:14:25 -07:00
redmatrix
86eb923f29 make guest access tokens work with PERMS_NETWORK, PERMS_SITE, PERMS_PENDING, and PERMS_CONTACTS; or everything but PERMS_SPECIFIC. PERMS_SITE could be contentious, but we're currently denying them as they are a guest and don't actually have a channel on this site. We can't easily make PERMS_SPECIFIC work without providing an abook entry for the guest since we would need to set specific permissions for the guest login, but unfortunately this could be the most desirable setting to use in many cases. There is also an update of hmessages.po in this commit. 2016-07-31 18:08:41 -07:00
hubzilla
14ca376902 Merge pull request #472 from einervonvielen/homeinstall-remove-owncloud
Homeinstall remove owncloud
2016-08-01 09:14:24 +10:00
hubzilla
77a9be845d Merge pull request #471 from einervonvielen/homeinstall-fix-letsencrypt-config-path
Homeinstall fix letsencrypt config path
2016-08-01 09:14:08 +10:00
hubzilla
9dd9e27fa8 Merge pull request #470 from einervonvielen/einervonvielen-fix-homeinstall-git-path
homeinstall - fix - path to git clone
2016-08-01 09:13:57 +10:00
hubzilla
74c68f09e5 Merge pull request #469 from anaqreon/website-import
Website import tool
2016-08-01 09:13:43 +10:00
Einer von Vielen
b60e36ea7a Changed homeinstall removed installation of owncloud from install
script
2016-07-31 18:53:28 +02:00
Einer von Vielen
fae7993f93 Fixed homeinstall script.
parameter --config has to be used after a change of letsencrpyt.sh
2016-07-31 18:38:45 +02:00
Einer von Vielen
215659a234 Merge remote-tracking branch 'mikemaster/master' 2016-07-31 18:05:16 +02:00
Andrew Manning
99afd0a449 Added help content for webpages app. Corrected apparent bug with capitalized Webpages.md 2016-07-31 10:20:03 -04:00
einervonvielen
c0e0379bab Merge pull request #2 from einervonvielen/einervonvielen-fix-homeinstall-git-path
homeinstall - fix - path to git clone
2016-07-31 15:27:45 +02:00
einervonvielen
c761531947 homeinstall - fix - path to git clone 2016-07-31 15:26:02 +02:00
Andrew Manning
42b718b3e0 Merge remote-tracking branch 'upstream/dev' into website-import 2016-07-31 07:38:44 -04:00
Andrew Manning
1e3a645abe Remove scanned element column for existing element information which we are not yet populating. 2016-07-31 07:37:33 -04:00
Andrew Manning
7c47557554 Improved UI. Removed logger statements. 2016-07-31 07:30:25 -04:00
redmatrix
da9b6690e5 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-07-30 14:04:30 -07:00
Andrew Manning
32366284a8 Import element selection page added to allow selective importing. 2016-07-30 09:56:47 -04:00
Andrew Manning
f17f51a9c1 Merge remote-tracking branch 'upstream/dev' into website-import 2016-07-30 06:30:46 -04:00
jeroenpraat
d858bd9265 Updating es-es strings 2016-07-29 14:31:53 +02:00
jeroenpraat
287e9c8d68 Updating es-es strings 2016-07-29 14:24:20 +02:00
Mario Vavti
5e5ec5a66a catch all input fields (in preparation for acl in this place) and display the files to upload in the right order 2016-07-29 11:30:33 +02:00
redmatrix
ae5c10a71c Merge branch '1.10RC' 2016-07-28 19:58:05 -07:00
redmatrix
4d5202353f Merge branch '1.10RC' of https://github.com/redmatrix/hubzilla into 1.10RC_merge 2016-07-28 18:26:32 -07:00
redmatrix
142bcd6806 move fixes to po2php forward to 1.10 2016-07-28 18:26:06 -07:00
hubzilla
7075697f60 Merge pull request #465 from phellmes/de20160728
Update DE translation strings
2016-07-29 09:55:47 +10:00
hubzilla
3a320462fa Merge pull request #467 from anaqreon/multiple-attach
Fixed bug where multiple post attachements by drag-and-drop were not …
2016-07-29 09:55:13 +10:00
redmatrix
856133b07d fix it strings after merge stuffup 2016-07-28 16:53:18 -07:00
redmatrix
0b2d809309 github didn't accept the last push. Touching the files to force a git revision 2016-07-28 16:47:08 -07:00
jeroenpraat
ec383aca03 Updated language files for release 2016-07-28 16:37:19 -07:00
Andrew Manning
8925e0c6c9 Fixed bug where multiple post attachements by drag-and-drop were not being added to the post content. 2016-07-28 19:21:33 -04:00
redmatrix
bc74425872 Revert "Merge branch '1.10RC' of https://github.com/redmatrix/hubzilla into 1.10RC_merge"
This reverts commit 35f17acb38, reversing
changes made to 58cf5f310d.
2016-07-28 16:02:51 -07:00
Mario Vavti
b15a53b672 missing space 2016-07-28 22:59:01 +02:00
Mario Vavti
ed7e4df014 missing semicolon 2016-07-28 22:57:07 +02:00
Mario Vavti
3bf2935ee3 add more info on what is happening after we are at 100% and minor fixes 2016-07-28 22:32:58 +02:00
redmatrix
35f17acb38 Merge branch '1.10RC' of https://github.com/redmatrix/hubzilla into 1.10RC_merge 2016-07-28 13:15:10 -07:00
redmatrix
58cf5f310d sql typo 2016-07-28 13:14:48 -07:00
redmatrix
2d916b531b Revert "issue #466, sql typo"
This reverts commit 4ce8f965aa.
2016-07-28 13:13:59 -07:00
redmatrix
12952c9821 issue #466, sql typo 2016-07-28 13:11:01 -07:00
redmatrix
4ce8f965aa issue #466, sql typo 2016-07-28 13:10:19 -07:00
jeroenpraat
47e1c4e059 Updated language files for release 2016-07-28 21:33:02 +02:00
jeroenpraat
47119ddc7d Merge branch '1.10RC' of https://github.com/redmatrix/hubzilla into 1.10RC 2016-07-28 21:07:46 +02:00
Mario Vavti
500ee4c1bf re-implement progress-bar to work with all browsers 2016-07-28 16:35:27 +02:00
Mario Vavti
fc105cf141 reusing the original form did not work so well via xhr upload - let us create a new form for this action. revert progressbar- only works nice in firefox 2016-07-28 15:35:45 +02:00
phellmes
18f0961caa Update DE translation strings 2016-07-28 14:09:29 +02:00
Mario Vavti
e65949f594 make progressbar slightly more transparent and give it a default width of 3px to indicate which files are to be uploaded 2016-07-28 11:54:42 +02:00
Mario Vavti
b05c1a9829 use single quote for js and double quote for html with proper escapes and implement a simple progressbar 2016-07-28 11:45:57 +02:00
Mario Vavti
9fa3956aa8 translate mime types to icons, update some icons, move file preview (upload progress) below table header 2016-07-28 10:28:48 +02:00
redmatrix
02fc082e45 github didn't accept the last push. Touching the files to force a git revision 2016-07-27 22:40:33 -07:00
redmatrix
be1ffca6f4 fix italian strings (messed up by rtl variable); and finish removing openid from core 2016-07-27 22:28:30 -07:00
hubzilla
987eb90e18 Merge pull request #464 from anaqreon/hover-visuals
Enhanced visual feedback for file drag hover
2016-07-28 12:07:01 +10:00
Andrew Manning
932aeebcf1 Enhanced visual feedback for file drag hover 2016-07-27 21:03:41 -04:00
redmatrix
5f3a8cbe93 add the hidden flag also 2016-07-27 16:14:46 -07:00
Mario Vavti
f808f1601b rework drag and drop to drag directly into files area, implement the default upload button to work with the same mechanism as drag and drop, revert 560af7a5b8 since it did not work so well with the new cloud upload mechanism 2016-07-27 16:49:55 +02:00
redmatrix
672c3d7c6d Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-07-26 22:51:07 -07:00
redmatrix
72479041ae don't include deleted or orphaned xchans in ratings search 2016-07-26 22:50:31 -07:00
hubzilla
e286b510f1 Merge pull request #463 from git-marijus/dev
allow multiple-file cloud upload
2016-07-27 14:54:51 +10:00
redmatrix
315dafbe12 restrict url cache to 254 maxlen 2016-07-26 20:05:40 -07:00
redmatrix
80e4338314 missing s 2016-07-26 19:28:28 -07:00
redmatrix
db176eec40 set App::$error on 404 so we don't get two 'Page not found.' page bodies. 2016-07-26 17:24:17 -07:00
redmatrix
02f88fc7b2 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-07-26 15:59:06 -07:00
redmatrix
56957b60e2 issue #460 - remove reference to $a which was passed by value since it doesn't exist. Ultimately $a needs to be removed completely but that's a bit messier. 2016-07-26 15:57:33 -07:00
Mario Vavti
7126fd4b31 fix drag and drop 2016-07-26 15:57:47 +02:00
Mario Vavti
560af7a5b8 allow multiple-file cloud upload 2016-07-26 13:17:46 +02:00
Wave
e38880a686 Merge pull request #462 from wave72/dev
Updated Italian strings
2016-07-26 09:51:54 +02:00
Wave72
29dd4ad39b Updated Italian strings 2016-07-26 09:51:06 +02:00
Mario Vavti
54ecf0f45f URLUtil path has changed since sabredav 1.8 - fixes renaming issue in dav clients 2016-07-26 09:05:38 +02:00
Mario Vavti
6900dd34a4 URLUtil path has changed since sabredav 1.8 - fixes renaming issue in dav clients 2016-07-26 09:04:52 +02:00
redmatrix
70dae328b5 check for new permissions and update channels and connections with defaults if any are found and if there are defaults for any channel roles which are being used on this site. 2016-07-25 21:59:52 -07:00
redmatrix
5d4245ff01 move openid to addon 2016-07-25 17:16:41 -07:00
redmatrix
24d28bc23a issue #460 2016-07-25 13:29:06 -07:00
redmatrix
d786eca126 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-07-25 13:27:42 -07:00
redmatrix
2fb4952137 issue #460 2016-07-25 13:27:17 -07:00
Mario Vavti
da512cef64 revert multiple test 2016-07-25 11:43:01 +02:00
Mario Vavti
f41b037fbe css fixes 2016-07-25 11:41:27 +02:00
redmatrix
0f5f1c98ca revert cloud acl selector (branched so as to continue development) 2016-07-25 01:46:40 -07:00
redmatrix
01338a7610 make drag/drop work with acl, which bypassed the form 2016-07-24 22:58:26 -07:00
redmatrix
063b4286e7 trace log pconfig cache if for some reason it isn't an array 2016-07-24 22:36:37 -07:00
redmatrix
271f85be3b add acl selection to files upload via /cloud (still missing from directory creation) 2016-07-24 20:27:59 -07:00
redmatrix
b5f2b4af35 string update and some minor comment edits 2016-07-24 16:11:34 -07:00
redmatrix
9967f2ab28 call wall_attach rather than wall_upload for drag/drop; which means you can drag/drop any file and not just photos. 2016-07-24 16:09:33 -07:00
hubzilla
52c3960946 Merge pull request #459 from anaqreon/jot-drag-attach
Drag and drop one image file at a time into the post editor will uplo…
2016-07-25 08:55:12 +10:00
Andrew Manning
1b1170bcf6 Drag and drop one image file at a time into the post editor will upload it. 2016-07-24 17:33:34 -04:00
hubzilla
eb03877aa4 Merge pull request #458 from anaqreon/dragdropupload
Drag-and-drop file upload for cloud files
2016-07-24 23:13:05 +10:00
Andrew Manning
4c4d185937 Remove logger calls 2016-07-24 08:35:21 -04:00
Andrew Manning
6998bb1f23 Multiple file upload by drag and drop with progress indicators and auto page reload 2016-07-24 07:41:53 -04:00
Andrew Manning
3a60bef2b6 Include credentials for session cookie in xhr 2016-07-23 08:39:23 -04:00
Andrew Manning
eb1eb38c01 AJAX single upload might be working, but permissions problems seem to cause failure. 2016-07-23 07:59:28 -04:00
Andrew Manning
3c5598407e Drag and drop file information display in cloud files upload form. No actual upload implemented yet. 2016-07-22 21:27:32 -04:00
Mario Vavti
4ffc4ee70a rename the patch so that it explains what it does 2016-07-22 14:29:16 +02:00
Mario Vavti
52db649022 apply our custom patch to readmore.js 2016-07-22 14:14:20 +02:00
Mario Vavti
38e46fff54 upgrade readmore.js and improve collapsing a little 2016-07-22 14:03:14 +02:00
Wave
744ad84714 Merge pull request #6 from redmatrix/dev
Dev
2016-07-22 10:55:02 +02:00
redmatrix
7d897a3f03 more work on #453 2016-07-21 23:06:55 -07:00
redmatrix
79eeeaee95 fix birthday addtocal 2016-07-21 21:36:10 -07:00
redmatrix
2c1b432613 fix birthday addtocal 2016-07-21 21:35:26 -07:00
redmatrix
0c3d5e99a2 PConfig : Check for is_null($uid) as well as false. We actually allow $uid = 0 though it shouldn't normally happen. 2016-07-21 20:50:39 -07:00
redmatrix
dca8a05026 Merge branch '1.10RC' of https://github.com/redmatrix/hubzilla into 1.10RC_merge 2016-07-21 20:06:08 -07:00
redmatrix
5cfc286972 zat URL auth updated to match changes to the atoken_login interface 2016-07-21 20:06:02 -07:00
redmatrix
bc46f70a90 zat URL auth updated to match changes to the atoken_login interface 2016-07-21 20:04:30 -07:00
Andrew Manning
5a63ddd645 Merge remote-tracking branch 'upstream/dev' into website-import 2016-07-21 21:14:54 -04:00
redmatrix
8566f91303 fail oembed if it is attempted and less than 80% of the original content is left after html filtering. For the original poster, this will fall back to linkinfo results. If the embed gets through their site but is filtered downstream (with more than 20% of the content removed), it will result in just a link. 2016-07-21 17:44:04 -07:00
Mario Vavti
b63aff77df merge 1.10RC into dev 2016-07-22 01:13:56 +02:00
Mario Vavti
5a1eb65ed6 missing $ 2016-07-22 01:07:53 +02:00
redmatrix
98a2dcad90 Merge branch '1.10RC' of https://github.com/redmatrix/hubzilla into 1.10RC_merge 2016-07-21 15:51:25 -07:00
redmatrix
77a021025f DAV auth issue 2016-07-21 15:51:10 -07:00
redmatrix
63123759ed DAV auth issue 2016-07-21 15:50:07 -07:00
redmatrix
6167291488 issue #411 2016-07-21 11:28:38 +02:00
redmatrix
cf0b1f1f15 typo 2016-07-21 01:48:20 -07:00
redmatrix
824dedbe9d issue #453 and a bug noted from the logfiles related to the schema change last month 2016-07-20 23:05:31 -07:00
redmatrix
da707736a0 issue #453 and a bug noted from the logfiles related to the schema change last month 2016-07-20 23:04:07 -07:00
redmatrix
8f57bb95fe undefined function 2016-07-20 21:57:15 -07:00
redmatrix
0c3543ac43 undefined function 2016-07-20 21:55:23 -07:00
redmatrix
d2e5b7cb76 delete test doc 2016-07-20 20:29:33 -07:00
redmatrix
6a56a509d3 Merge branch 'dev' into perms 2016-07-20 19:03:18 -07:00
redmatrix
dffa08adcc fix vevent multi-line formatting 2016-07-20 19:00:45 -07:00
redmatrix
779885f9af fix vevent multi-line formatting 2016-07-20 18:59:51 -07:00
Andrew Manning
d504197a78 Merge remote-tracking branch 'upstream/dev' into website-import 2016-07-20 21:22:53 -04:00
redmatrix
542fcaff9a Merge branch '1.10RC' of https://github.com/redmatrix/hubzilla into 1.10RC_merge 2016-07-20 17:57:42 -07:00
redmatrix
bc8c74eb42 sort out some of the authentication mess - with luck this may fix the DAV auth issue which I simply could not duplicate or find a reason for. 2016-07-20 17:57:17 -07:00
redmatrix
3affb2e817 sort out some of the authentication mess - with luck this may fix the DAV auth issue which I simply could not duplicate or find a reason for. 2016-07-20 17:55:40 -07:00
redmatrix
df0cd4dbc7 Merge branch 'dev' into perms 2016-07-20 13:39:10 -07:00
Mario Vavti
d54ad98802 Merge branch '1.10RC' into dev 2016-07-20 22:01:58 +02:00
Mario Vavti
1d90c4ea99 Merge branch '1.10RC' of https://github.com/redmatrix/hubzilla into 1.10RC 2016-07-20 22:00:58 +02:00
Mario Vavti
4da005e209 type m query in Acl.php should probably^Ceturn xchan_hash as hash and not as id. This fixes the issue that autocomplete for mail returns null for data.xid 2016-07-20 22:00:41 +02:00
git-marijus
c3149a8d59 Merge pull request #456 from anaqreon/1.10RC-updates
Wiki delete page confirmation and max image width
2016-07-20 20:50:50 +02:00
git-marijus
fd507ff597 Merge pull request #455 from anaqreon/wiki
Wiki delete page confirmation and max image width
2016-07-20 20:50:17 +02:00
Mario Vavti
8c2b93da72 Merge branch '1.10RC' into dev 2016-07-20 20:44:20 +02:00
Mario Vavti
ca82b45fe4 fix /mail wsod issue reported by giac hellvecio 2016-07-20 20:43:12 +02:00
Andrew Manning
da49befb18 Wiki delete page confirmation and max image width 2016-07-20 05:44:29 -04:00
Andrew Manning
e0d9d30bcf Merge remote-tracking branch 'upstream/dev' into wiki 2016-07-20 05:39:08 -04:00
Andrew Manning
99f7dd0fd4 Merge remote-tracking branch 'upstream/dev' into website-import 2016-07-20 05:38:19 -04:00
Andrew Manning
0c7ad924a8 Starting to make the import selection page after element scan. 2016-07-20 05:33:40 -04:00
redmatrix
a3e5307b93 fix the forum detection in include/zot 2016-07-19 22:57:23 -07:00
redmatrix
ae6256f95a another couple of minor perms fixes 2016-07-19 22:32:22 -07:00
redmatrix
a961d5e6c8 permission fixes 2016-07-19 20:49:54 -07:00
redmatrix
237cca7a0d fixes to perms 2016-07-19 19:33:48 -07:00
redmatrix
2c9938f0d5 add test sequence 2016-07-19 18:41:36 -07:00
redmatrix
ea83032863 translate more old perms calls 2016-07-19 17:52:45 -07:00
redmatrix
6a4573b935 Merge branch 'dev' into perms 2016-07-19 17:05:59 -07:00
redmatrix
9421e42dad doc correction 2016-07-19 17:04:38 -07:00
redmatrix
f4b658d7b1 issue #411 2016-07-19 05:13:18 -07:00
redmatrix
7272b97e9a yet more grungy perms work. 2016-07-19 01:26:28 -07:00
redmatrix
8a9f062b95 Merge branch 'dev' into perms 2016-07-18 22:35:31 -07:00
redmatrix
eac35c05e9 Merge branch '1.10RC' of https://github.com/redmatrix/hubzilla into 1.10RC_merge 2016-07-18 22:34:16 -07:00
redmatrix
07b96f2430 runaway cron emails 2016-07-18 22:34:07 -07:00
redmatrix
269b3cef72 runaway cron emails 2016-07-18 22:33:26 -07:00
redmatrix
99cf2cbaa9 missing bracket 2016-07-18 21:46:40 -07:00
redmatrix
b63165b6e0 more perms work (a lot more) 2016-07-18 21:37:34 -07:00
redmatrix
32ce790717 move legacy code inside the legacy check 2016-07-18 19:09:27 -07:00
redmatrix
b5b57523f1 more perms work 2016-07-18 16:45:43 -07:00
redmatrix
7524948a97 Merge branch 'dev' into perms 2016-07-18 16:10:41 -07:00
redmatrix
f9b67d3630 more perms work 2016-07-18 13:44:39 -07:00
Mario Vavti
3beb94dc52 whitespace 2016-07-18 13:52:26 +02:00
Mario Vavti
4371e6ad97 resolve merge conflict 2016-07-18 13:50:32 +02:00
Mario Vavti
f44ca74e99 do not transform hashes to tags in [code=xxx] or [code] blocks 2016-07-18 13:48:09 +02:00
redmatrix
10fa5c20e7 export/import channel permissions 2016-07-17 22:40:39 -07:00
redmatrix
f7833411a1 clone channel perms 2016-07-17 22:18:35 -07:00
redmatrix
de4f9d68bd Merge branch 'dev' into perms 2016-07-17 21:40:04 -07:00
redmatrix
571b8cc85b roll version 2016-07-17 19:57:19 -07:00
redmatrix
883fc5d753 update changelog 2016-07-17 19:56:32 -07:00
redmatrix
25b2a6e0cf update changelog 2016-07-17 19:54:59 -07:00
redmatrix
4febdc3bcd jquery update issue prevents comments from reloading and resetting watch cursor 2016-07-17 18:33:45 -07:00
redmatrix
c3617f5d1e jquery update issue prevents comments from reloading and resetting watch cursor 2016-07-17 18:32:38 -07:00
redmatrix
fc78ba7c2f change std_version 2016-07-17 16:38:21 -07:00
redmatrix
279359c1bd Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-07-17 16:05:46 -07:00
redmatrix
dc9fa7cf64 include attach.php at the module level since 2d4b75428a wasn't backported to dev and we're about to branch an RC 2016-07-17 16:04:00 -07:00
Andrew Manning
d6b28cdc57 Importing webpage elements from manually entered cloud file path work. All detected elements are automatically imported. 2016-07-17 16:05:26 -04:00
Andrew Manning
75fb065526 Merge remote-tracking branch 'upstream/dev' into website-import 2016-07-17 11:54:36 -04:00
Andrew Manning
6c5086a933 Added functions to check cloud files path and return path with hashed names 2016-07-17 11:52:21 -04:00
Mario Vavti
2b674d4cd9 hide fullscreen button in embedphotos modal album view 2016-07-17 12:54:10 +02:00
redmatrix
5d0ddb3123 booboo 2016-07-17 02:49:41 -07:00
hubzilla
2d4b75428a Merge pull request #452 from anaqreon/patch-1
Fixed whitescreen when creating folders via cloud files web interface
2016-07-17 19:40:26 +10:00
Mario Vavti
f39d20ac97 some work on guest access token ui 2016-07-17 11:29:37 +02:00
Andrew Manning
db2b6f1268 Fixed whitescreen when creating folders via cloud files web interface
I'm getting a "not found" error when I try to create folders in the cloud files web interface. I click the "Create" button beside the "Upload" button, type a bland name for a new folder, and I get a white screen. Including the attach.php file fixes the bug.

Version 1.9.1+99354ac
2016-07-16 21:23:29 -04:00
Andrew Manning
99354ac576 Merge remote-tracking branch 'upstream/dev' into website-import-remote 2016-07-16 21:04:04 -04:00
Andrew Manning
e7b8531751 Stash changes to merge from dev 2016-07-16 21:02:13 -04:00
Andrew Manning
ff2f599142 Postpone remote folder import until filesystem mirroring matures. 2016-07-16 19:25:44 -04:00
Mario Vavti
f396b1bf73 check for variables after schema files have been added 2016-07-16 16:18:36 +02:00
Mario Vavti
e237dfc660 check for variables in schemes 2016-07-16 12:32:22 +02:00
Mario Vavti
641029ab18 hide/show mixup 2016-07-16 10:56:46 +02:00
Mario Vavti
065ef29de2 only use visibility for tabs 2016-07-16 10:52:06 +02:00
redmatrix
aac0fa2b5f os_delete_prohibit 2016-07-16 01:02:41 -07:00
redmatrix
17edec8e4a add new service class restriction to the doco 2016-07-15 21:59:41 -07:00
redmatrix
8e667866fd add service class restrictions to access_tokens 2016-07-15 21:57:41 -07:00
redmatrix
01fe7d6620 remove expired access tokens 2016-07-15 17:34:44 -07:00
redmatrix
f3aff45042 provide examples for using access tokens in urls 2016-07-15 16:31:21 -07:00
redmatrix
d6d94d9427 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-07-15 15:31:50 -07:00
redmatrix
acb78205c8 login isn't always your email. 2016-07-15 15:30:52 -07:00
redmatrix
dcb3c2c299 mod_home: if using an atoken login on the home page redirect to the channel page of the channel that owns the atoken. 2016-07-15 15:26:36 -07:00
Mario Vavti
9048f8cffe bump minor version because of jquery update 2016-07-15 14:53:15 +02:00
Mario Vavti
4a2fb8336e round up height 2016-07-15 14:23:10 +02:00
Mario Vavti
34a16e0ab9 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-07-15 13:21:07 +02:00
Mario Vavti
c2779b6f33 add jquery migrate for version 3 2016-07-15 13:20:55 +02:00
Mario Vavti
2e32b5f467 upgrade to jquery-3.1 and minor fixes 2016-07-15 13:20:00 +02:00
redmatrix
da5ec98f98 make lockview work with throwaway identities 2016-07-15 02:07:27 -07:00
redmatrix
d54f5a3831 more cleanup of atoken UI 2016-07-15 01:43:09 -07:00
redmatrix
5e475acb85 cleanup and debug of atoken feature 2016-07-15 01:33:28 -07:00
redmatrix
f666d8a083 enforce non-empty name and token/password on access tokens until better checks are instituted. 2016-07-15 01:06:25 -07:00
redmatrix
7ee7f00bf3 Here's the basic UI for the Zot Access Tokens, requires some minor cleanup 2016-07-14 22:41:53 -07:00
redmatrix
397a23499d make the xchan_hash for the access token location independent 2016-07-14 21:28:17 -07:00
redmatrix
d660bde324 missing brace 2016-07-14 20:53:38 -07:00
redmatrix
94bd53c0f1 schema updates for zot access tokens 2016-07-14 20:51:15 -07:00
redmatrix
f70f4a4e85 add zat to acl 2016-07-14 20:26:22 -07:00
redmatrix
f3eb9af046 more ZAT work 2016-07-14 19:43:47 -07:00
Andrew Manning
0edf248cd1 Merge remote-tracking branch 'upstream/dev' into website-import 2016-07-14 22:25:30 -04:00
Andrew Manning
514ffb74aa Refactored the scan and import functions to reduce redundant code and simplify logic. Import of pages, layouts, and blocks works. 2016-07-14 22:24:23 -04:00
redmatrix
e6c8614801 first cut at zot access tokens 2016-07-14 19:24:15 -07:00
redmatrix
05a9f2f0f5 markdown is whitespace sensitive 2016-07-14 17:46:21 -07:00
redmatrix
115ef3249c who are we 2016-07-14 17:45:09 -07:00
redmatrix
191cd21028 more perms work 2016-07-13 23:05:19 -07:00
redmatrix
b3a785711c deprecate/remove json_decode_plus 2016-07-13 22:11:06 -07:00
redmatrix
503b420292 rework perm_is_allowed 2016-07-13 20:23:20 -07:00
redmatrix
0aa205044b Merge branch 'dev' into perms 2016-07-13 20:19:11 -07:00
redmatrix
00afe56cad let abconfig specify a family 2016-07-13 20:17:40 -07:00
redmatrix
1fd65c934d lots more permission work 2016-07-13 19:53:28 -07:00
Andrew Manning
960e9edff5 Blocks, pages, and layouts import from zip file. Layouts are not applied to pages until imported twice though. 2016-07-13 21:46:59 -04:00
redmatrix
b72720f6b6 Merge branch 'dev' into perms 2016-07-13 18:24:45 -07:00
redmatrix
f60a0c5ce0 document mod_acl a bit better and try to remove some redundancies and consolidate the various options 2016-07-13 17:51:19 -07:00
Andrew Manning
ba903e21ed Updated import_blocks for database calls 2016-07-13 06:17:12 -04:00
Andrew Manning
75b943b98a Merge remote-tracking branch 'upstream/dev' into website-import 2016-07-13 05:50:31 -04:00
redmatrix
18565600b2 missing namespace prefix \ 2016-07-12 22:58:12 -07:00
redmatrix
f4e4e734de more work on perms 2016-07-12 21:47:24 -07:00
redmatrix
6424bac47c Merge branch 'dev' into perms 2016-07-12 20:50:27 -07:00
redmatrix
bdd7d24ac1 update_remote_id - updated to work with iconfig 2016-07-12 19:08:36 -07:00
Andrew Manning
5131759823 Merge remote-tracking branch 'upstream/dev' into website-import 2016-07-12 21:43:05 -04:00
Andrew Manning
1e4ef81244 Import blocks from zip file, but needs updates as detailed in https://gitlab.com/zot/hubsites/merge_requests/2 2016-07-12 21:41:37 -04:00
redmatrix
0fa807e7ad don't try to send sync packets to dead sites. 2016-07-12 18:38:39 -07:00
redmatrix
b6987b4287 the abconfig defaults weren't changed in the schema files when they were changed in the code 2016-07-12 13:15:20 -07:00
redmatrix
ed0e2b52d7 move permissiondescription class to zotlabs/lib 2016-07-11 21:46:16 -07:00
redmatrix
168d35747d use the get_hostname function rather than parse the url 2016-07-11 18:59:54 -07:00
redmatrix
a01baab4f0 Merge branch 'dev' into perms 2016-07-11 17:45:10 -07:00
redmatrix
17c3e12eab document the new change_channel hook 2016-07-11 17:43:10 -07:00
redmatrix
71b001fdb7 more perms work - notably the stuff in public_perms 2016-07-11 17:02:49 -07:00
redmatrix
833de9180e create change_channel hook 2016-07-11 13:46:06 -07:00
redmatrix
fb36561a68 force non-null sess_data 2016-07-11 13:27:44 -07:00
redmatrix
67c60229ca use the profile_uid here. 2016-07-11 13:20:12 -07:00
redmatrix
f4bcb82041 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-07-11 13:19:13 -07:00
Habeas Codice
983ccef87c NOT NULL constraint without default and INSERT does not provide one 2016-07-11 10:55:42 -07:00
Mario Vavti
a849dcadb6 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-07-11 12:50:12 +02:00
Mario Vavti
d5afd0d7c2 do not use visibility for fullscreen button and move fullscreen button to the right 2016-07-11 12:49:53 +02:00
redmatrix
cc83983ae5 perms work 2016-07-10 17:45:14 -07:00
hubzilla
ba5183b244 Merge pull request #451 from git-marijus/dev
remove check for mcrypt
2016-07-11 09:06:11 +10:00
Mario Vavti
3d3584b36c remove check for mcrypt 2016-07-10 13:42:04 +02:00
Andrew Manning
c5e534c0cb Clearer import control interface 2016-07-10 07:21:52 -04:00
Andrew Manning
a338a97d5b First draft of website import tools 2016-07-10 06:58:20 -04:00
Mario Vavti
e11219888d Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-07-10 11:34:10 +02:00
redmatrix
e6638b4715 change default so we don't have to check for array existence later 2016-07-09 21:23:00 -07:00
redmatrix
c9db8c6857 more permissions work 2016-07-09 21:08:02 -07:00
redmatrix
917a465ccd more work on perms 2016-07-09 19:03:29 -07:00
redmatrix
ce5adbf51e more sql fine tuning 2016-07-09 18:10:13 -07:00
Andrew Manning
50e581d88a Set max-width for embedded images 2016-07-09 20:24:16 -04:00
Andrew Manning
47d7fc70e8 Merge remote-tracking branch 'upstream/dev' into wiki 2016-07-09 20:17:20 -04:00
redmatrix
e2574cf069 some work on the forum widget queries 2016-07-09 16:07:53 -07:00
redmatrix
ee1ec0428b gak one more typo 2016-07-07 18:53:09 -07:00
redmatrix
3b17dca252 typo 2016-07-07 18:51:56 -07:00
redmatrix
eef40cb3fd duplicate supression SQL query was horribly inefficient and could cause issues in resource deprived environments. 2016-07-07 18:47:18 -07:00
hubzilla
9f413ed174 Merge pull request #450 from git-marijus/dev
fix /cloud after recent changes
2016-07-08 10:40:59 +10:00
redmatrix
233cfc29d6 hide the redeliver option one level down since it should rarely be needed by folks outside of shared hosting. 2016-07-07 17:23:52 -07:00
redmatrix
e11330a5c8 revise how we store perm_limits 2016-07-07 16:44:58 -07:00
Mario Vavti
0b2ad9deca Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-07-07 20:39:52 +02:00
Mario Vavti
227320f6f0 more fixes for /cloud and /dav 2016-07-07 20:16:27 +02:00
redmatrix
3bee6543fb reduce the memory usage of the expire query dramatically. 2016-07-06 22:19:05 -07:00
redmatrix
581a3c5323 expire crashing on shared hosting from memory exhaustion. Lower the expire limit. Also the sys channel was being expired with everybody else due to a flag change regression. 2016-07-06 22:02:06 -07:00
Mario Vavti
a59e84cadd Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-07-06 21:31:17 +02:00
Mario Vavti
d4627a0b1c fix /cloud after recent changes 2016-07-06 21:31:05 +02:00
redmatrix
08a4763bff more work on permissions 2016-07-05 20:21:47 -07:00
redmatrix
537f30f707 Merge branch 'dev' into perms 2016-07-05 19:40:09 -07:00
redmatrix
ad954d01de unused file 2016-07-05 17:57:36 -07:00
redmatrix
e3d70e6b62 merge include/reddav.php into Zotlabs/Storage/Directory.php 2016-07-05 17:54:05 -07:00
redmatrix
cbf009a95d cleanup 2016-07-05 16:56:40 -07:00
redmatrix
35cc763a92 regression - save bookmarks no longer present in item menu 2016-07-05 16:24:45 -07:00
redmatrix
cf05111622 start to refactor the permission roles 2016-07-04 22:37:30 -07:00
redmatrix
e6224898d2 more heavy lifting on xtensible perms 2016-07-04 21:33:25 -07:00
redmatrix
d566ffa678 more heavy lifting on extensible perms 2016-07-04 17:55:13 -07:00
redmatrix
6bf2e8a108 some perms fixes to stuff that was already written before I move on 2016-07-04 16:30:03 -07:00
redmatrix
805ecde6a5 minor 2016-07-04 00:12:53 -07:00
redmatrix
2a26b0ae91 perms work - settings page 2016-07-03 22:47:46 -07:00
redmatrix
916e088462 make permissionlimits into a class 2016-07-03 18:20:15 -07:00
redmatrix
c918bbba25 more work on x permissions 2016-07-03 17:10:00 -07:00
redmatrix
57226b2e13 Merge branch 'dev' into perms 2016-07-03 15:58:20 -07:00
hubzilla
f46eecc1e7 Merge pull request #448 from Treer/avatars
Force local cache update when user changes their profile picture
2016-07-04 06:38:49 +10:00
Treer
5c062aaec4 force immediate avatar update 2016-07-03 22:38:05 +10:00
Treer
b87106b6fe Mark nickname as required field, if left empty then channel creation fails silently 2016-07-03 17:59:44 +10:00
redmatrix
523e7b5084 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-07-01 20:48:49 -07:00
redmatrix
41fa2d6c69 delivery invoked twice in mod_tagger, once in post_activity_item() and another at the main module level 2016-07-01 20:46:57 -07:00
redmatrix
5947467339 use small photo for Diaspora attribution correction; the medium looks awkward in the D* stream. 2016-07-01 20:34:00 -07:00
Mario Vavti
0a11991340 use visibility instead of display to hide elements 2016-07-01 12:58:15 +02:00
Andrew Manning
0630609d6e Merge remote-tracking branch 'upstream/dev' into wiki 2016-07-01 06:36:25 -04:00
Andrew Manning
205924ff29 JavaScript popup for page delete confirmation 2016-07-01 06:35:49 -04:00
Mario Vavti
7371e08625 ditch the change_view widget and make header fixed in fullscreen mode 2016-07-01 12:21:19 +02:00
redmatrix
bb5ec8cfb8 allow multiple apd's per plugin dir 2016-07-01 02:16:23 -07:00
redmatrix
e6c8de5e4c if cron is broken because the entire db or config table is crashed, don't send a cron broken email - because we have no way of limiting it to just one email. We need a working config to do that. 2016-06-30 21:43:00 -07:00
redmatrix
bd403276f2 disable wiki if feature disabled, sync updates of delayed publish posts 2016-06-30 21:27:59 -07:00
redmatrix
7f8dcf4f12 sync flags even if post has not been edited 2016-06-30 21:12:39 -07:00
hubzilla
eef8f3b417 Merge pull request #445 from anaqreon/wiki
Table of contents with links is generated if [toc] is found in Markdown text
2016-07-01 11:57:48 +10:00
Andrew Manning
0fd8eeec23 Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-30 21:51:33 -04:00
Andrew Manning
7124c0aee5 Replace homemade table of content generator with existing jQuery plugin. Now toc is linked to document headings. 2016-06-30 21:50:38 -04:00
Mario Vavti
852b2659e9 update moment.js to version 2.13 2016-06-30 21:56:00 +02:00
redmatrix
1cc816f662 dreport: convert timestamp to channel localtime and get rid of old pre-template code 2016-06-29 22:53:18 -07:00
redmatrix
bfe84a9ff7 templatise the Dreport page and add a redeliver option for when things stuff up badly. 2016-06-29 22:46:47 -07:00
redmatrix
339e620738 wiki featured disabled by default in UNO. 2016-06-29 21:03:53 -07:00
redmatrix
9ef710c557 provide wiki as a feature (default is on so there aren't any surprises) and add to channel menu and profile tabs 2016-06-29 20:59:00 -07:00
redmatrix
df4ff26845 only request geolocation permission if we're creating a post. 2016-06-29 17:53:59 -07:00
redmatrix
2e93a09d83 stream large photos through buffered I/O if possible 2016-06-29 17:31:48 -07:00
hubzilla
05aba0b4dd Merge pull request #444 from git-marijus/dev
Merge branch sabre32 into dev
2016-06-30 09:34:22 +10:00
Mario Vavti
f098600c41 missing backslash leads to wsod on refresh permissions 2016-06-29 23:04:34 +02:00
Mario Vavti
ad83825d4f missing backslash leads to wsod on refresh permissions 2016-06-29 22:50:40 +02:00
Mario Vavti
3102440d40 Merge branch 'dev' into sabre32 2016-06-29 09:11:22 +02:00
redmatrix
715b1667d9 readability 2016-06-28 20:48:43 -07:00
redmatrix
7d62e087c6 identity_export_year() was a bit short-sighted. We really require arbitrary date ranges. A new function was created to tackle this - channel_export_items() which takes a channel, and a start and finish date. Finish date will default to "now" if not set. Will be working this into the interface under a module named "export_items" which will correspond closely to the existing "import_items" module you'll need to do the reverse operation. Will also make it available via the API. Once that is complete, I anticipate removing identity_export_year() as it will then be somewhat redundant, and modifying the documentation on the channel export page accordingly. Note: the function works strictly in GMT so an interface would need to convert from channel local time. 2016-06-28 13:36:48 -07:00
Mario Vavti
dcc65bbacb update to sabre/dav to version 3.2.0 2016-06-28 21:45:14 +02:00
Mario Vavti
feaad50b6c Merge branch 'dev' into sabre32 2016-06-28 13:45:00 +02:00
Mario Vavti
7b2d54dffa fix month view in fullscreen mode 2016-06-28 13:44:32 +02:00
Mario Vavti
e170217c33 erge branch 'dev' into sabre32 2016-06-28 11:57:03 +02:00
Mario Vavti
aff58934c0 update fullcalendar to version 2.8.0 2016-06-28 11:56:28 +02:00
Mario Vavti
9f576369a9 Merge branch 'dev' into sabre32 2016-06-28 11:09:22 +02:00
redmatrix
7d7f43c205 still working through some issues with curl magic-auth
fixed profile photo upload
2016-06-27 22:25:37 -07:00
redmatrix
30a5fe3061 provide a daemon for implementing zot magic-auth over curl. 2016-06-27 19:53:35 -07:00
redmatrix
b155e93ab1 add letsencrypt x3 intermediate cert and new cert file, improve UX of new registrations 2016-06-27 19:04:00 -07:00
redmatrix
3704ff57cb replace [+] and [-] with chevron icons 2016-06-27 16:50:06 -07:00
redmatrix
ee1d527497 comment on the setup page about the possible need for intermediate certs. 2016-06-27 16:15:47 -07:00
Habeas Codice
f40f7b4d6e typos 2016-06-27 16:06:09 -07:00
Mario Vavti
911510f999 Merge branch 'dev' into sabre32 2016-06-27 22:14:42 +02:00
Habeas Codice
45f5ac560d typos 2016-06-27 06:28:08 -07:00
redmatrix
fe7020e2f8 start on re-write of the permissions doc. Some of this will change (slightly), as the permissions framework is currently evolving. Most of the concepts and mechanisms will remain the same, but we need to simplify and do a better job of explaining the concepts. 2016-06-27 05:18:35 -07:00
redmatrix
17e161006a added permissionroles 2016-06-27 04:44:10 -07:00
redmatrix
85d2ad4aea Merge branch 'dev' into perms 2016-06-27 04:00:10 -07:00
Mario Vavti
5b9cd0af64 Merge branch 'dev' into sabre32 2016-06-27 09:54:01 +02:00
redmatrix
8d298d5a06 fix for the rendering side of issue #412. We traditionally store all
"user generated" content with ENT_COMPAT encoding to reduce the attack
vector for JS CSS exploits. This may present compatibility issues sharing
wikis to platforms which do not provide such CSS protection. We can either
decide that wikis are inherently insecure and filter them on render (with
an associated performance penalty), or keep the existing method of filtering
on store. I'm not making that choice. I'm merely fixing the obvious rendering
issue in mono-platform viewing.
2016-06-26 22:26:45 -07:00
redmatrix
3035c792dc remove the app $a passed to profile_load, also add profile_load to mod_wiki which should fix issue #431 2016-06-26 22:13:59 -07:00
redmatrix
2029b2b9ed document the daemon classes 2016-06-26 21:58:09 -07:00
redmatrix
900d8f3b0a Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-26 20:17:12 -07:00
redmatrix
e2de2f65d5 issue #442, tables contain too much whitespace (there's a definite issue here, but I should note the offending example was full of carriage returns as well as linefeeds; which exacerbated the problem). 2016-06-26 20:15:42 -07:00
Andrew Manning
81da9f99e4 Fixed bug with rendering table of contents upon page load 2016-06-26 15:41:25 -04:00
Andrew Manning
216f034b6d Also generate table of contents when loading the page 2016-06-26 15:27:55 -04:00
Andrew Manning
b96edd8b9a Added table of contents generator. Table is inserted wherever [toc] is encountered. 2016-06-26 15:04:47 -04:00
Mario Vavti
27ee95106d Merge branch 'dev' into sabre32 2016-06-26 08:59:58 +02:00
hubzilla
dac3138fd1 Merge pull request #441 from Treer/cdn
fix absolute .js urls
2016-06-26 13:43:07 +10:00
Treer
e0a7637626 fix absolute .js urls 2016-06-26 13:08:40 +10:00
hubzilla
8c4481733f Merge pull request #438 from anaqreon/wiki
Wiki post generation option and image embed tool
2016-06-26 08:25:31 +10:00
hubzilla
d20e62dcd3 Merge pull request #440 from Treer/misc
fix help link
2016-06-26 08:25:06 +10:00
hubzilla
7805a3c527 Merge pull request #439 from Treer/cdn
Allow absolute links to css and js files (for CDN links)
2016-06-26 08:22:16 +10:00
Andrew Manning
0df3978cc5 A page name wrapped in double brackets is converted into a link to another page in the current wiki 2016-06-25 14:29:52 -05:00
Treer
bd4a88cd3e fix help link 2016-06-26 03:17:10 +10:00
Treer
2dc1236dca Allow absolute links to css and js files 2016-06-25 22:38:15 +10:00
Mario Vavti
2528d97f52 Merge branch 'dev' into sabre32 2016-06-25 13:58:24 +02:00
Andrew Manning
241b257556 Insert image links wherever cursor is in the editor 2016-06-25 06:50:24 -05:00
Andrew Manning
83a42afddf Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-25 06:30:15 -05:00
Andrew Manning
780f83a118 Post generation about new wiki is optional, default is NOT to post. Fixed bug in wiki creation. Added embed image dialog and album browser. 2016-06-25 06:27:14 -05:00
Alexandre Hannud Abdo
ec3651d216 Improvements to help pages 2016-06-25 04:13:29 -07:00
redmatrix
6154fc7686 Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-06-25 04:11:03 -07:00
redmatrix
1924459abd media (e.g. video) files weren't being detected correctly in oembed, causing the stream to try and load large videos (and failing) 2016-06-25 04:10:48 -07:00
redmatrix
f66576f366 media (e.g. video) files weren't being detected correctly in oembed, causing the stream to try and load large videos (and failing) 2016-06-25 04:09:07 -07:00
hubzilla
7470fc7f24 Merge pull request #437 from solstag/help
Improvements to help pages
2016-06-25 20:24:28 +10:00
Alexandre Hannud Abdo
0e041a3b64 Improvements to help pages 2016-06-25 00:18:24 +00:00
Mario Vavti
c8ae04a96a Merge branch 'dev' into sabre32 2016-06-24 11:25:20 +02:00
redmatrix
c809b6f95e Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-24 02:18:26 -07:00
redmatrix
1577efa25e fix pdledit list mode 2016-06-24 02:17:25 -07:00
redmatrix
fb93ae2128 fix pdledit "list layouts" 2016-06-24 02:07:12 -07:00
hubzilla
25c9e9ef93 Merge pull request #435 from dissolve/microformats2
add url permalink mf2 markup
2016-06-24 14:55:56 +10:00
Ben Roberts
812dc9e898 add url permalink mf2 markup 2016-06-24 00:45:39 -04:00
hubzilla
bf4b698573 Merge pull request #434 from dissolve/microformats2
p-author missing from embedded h-card in items
2016-06-24 13:58:01 +10:00
Ben Roberts
5162c55e5d p-author missing from embedded h-card in items 2016-06-23 23:46:02 -04:00
redmatrix
096619dbbe make dropdown-caret invoke the dropdown 2016-06-23 20:13:20 -07:00
redmatrix
fa02a09107 SuperCurl to provide a re-usable curl options stack and just change options that are different from one call to the next 2016-06-23 20:05:57 -07:00
redmatrix
51e2ef39c2 db update for abconfig transition 2016-06-23 18:35:01 -07:00
redmatrix
b19bbf5473 change AbConfig to use channel_id instead of channel_hash; which was a mistake in retrospect 2016-06-23 18:12:26 -07:00
redmatrix
e5c66d94f2 relocate the cache class 2016-06-23 05:18:58 -07:00
redmatrix
2a32713dfc Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-23 01:18:17 -07:00
redmatrix
acf26d5c63 code cleanup for profile_photos 2016-06-23 01:17:44 -07:00
Mario Vavti
39b14b6b81 Merge branch 'dev' into sabre32 2016-06-23 10:14:13 +02:00
hubzilla
ac81a3a5ef Merge pull request #433 from dissolve/microformats2
microformats 2 for posts
2016-06-23 14:39:26 +10:00
Ben Roberts
ab628eb2a3 microformats 2 for posts 2016-06-22 23:59:27 -04:00
redmatrix
b8c5a91940 set profile when "use existing photo" 2016-06-22 20:46:44 -07:00
redmatrix
f7d2c99a3a move revision up 2016-06-22 20:18:29 -07:00
redmatrix
32408ed6a3 missing class selector when "use photo as profile photo" 2016-06-22 20:18:08 -07:00
redmatrix
515b054a6e missing class selector when "use photo as profile photo" 2016-06-22 20:17:19 -07:00
redmatrix
cef77ce5bb the xchan_query wasn't fully optimised as we were comparing quoted and unquoted strings when looking for duplicates 2016-06-22 19:22:59 -07:00
redmatrix
1267d995ef db statement debugging 2016-06-22 19:08:59 -07:00
redmatrix
ec8091a102 use the normal html escape for '@' in addresses rather than the high-plane unicode variant. This makes it copy-able, but not easily scrape-able. 2016-06-22 18:00:18 -07:00
Mario Vavti
5536df51f5 erge branch 'dev' into sabre32 2016-06-22 09:58:55 +02:00
redmatrix
f48b12ff52 provide a skeleton of the current CalDAVClient with lots of notes about how best to move forward just in case anybody is feeling ambitious or anxious. 2016-06-21 20:44:55 -07:00
redmatrix
415a8d1e01 channel homepage not providing content when javascript disabled 2016-06-21 19:42:08 -07:00
redmatrix
2a840460dd vcard spec changes 2016-06-21 19:25:14 -07:00
redmatrix
12f114c4be Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-21 18:26:16 -07:00
redmatrix
b593c3a9b9 1. provide automatic relocation of important links in items that are imported or synced to clones
2. provide framework for custom curl request bodies using custom/non-standard request methods. This was a real nightmare because curl doesn't actually let you specify a string to send as the request body (except when doing POST). You have to treat it as a file upload using a custom file handler function which provides the actual content in chunks as if it were buffered I/O.
3. item_store and item_store_update now return the item that was stored
2016-06-21 18:24:36 -07:00
redmatrix
8fa26db1b3 1. provide automatic relocation of important links in items that are imported or synced to clones
2. provide framework for custom curl request bodies using custom/non-standard request methods. This was a real nightmare because curl doesn't actually let you specify a string to send as the request body (except when doing POST). You have to treat it as a file upload using a custom file handler function which provides the actual content in chunks as if it were buffered I/O.
2016-06-21 18:18:06 -07:00
Mario Vavti
ecae0b3d97 Merge branch 'dev' into sabre32 2016-06-21 10:08:49 +02:00
redmatrix
63423c8ee1 make sure the optimisations are reliable 2016-06-20 20:56:58 -07:00
redmatrix
ed16660867 code optimisation 2016-06-20 20:34:19 -07:00
redmatrix
9c9d6363af update attach on import if exists 2016-06-20 19:39:12 -07:00
redmatrix
3a43b1d85d Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-20 13:43:36 -07:00
redmatrix
76f07a7f97 Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-06-20 13:42:51 -07:00
redmatrix
4d219df04e fix siteinfo plugin list 2016-06-20 13:42:39 -07:00
redmatrix
01bfadaeaa fix siteinfo plugin list 2016-06-20 13:42:04 -07:00
hubzilla
670d12219b Merge pull request #429 from anaqreon/wiki
Wiki page revision comparison viewer
2016-06-21 06:23:58 +10:00
Mario Vavti
da2c0a22f9 Merge branch 'dev' into sabre32 2016-06-20 22:05:03 +02:00
Mario Vavti
953ac6f3c7 last merge from master did reset the std_version to 1.8 - set it back to 1.9 for dev 2016-06-20 22:03:39 +02:00
Mario Vavti
545219b839 Merge branch 'dev' into sabre32 2016-06-20 21:47:49 +02:00
Mario Vavti
985fb44424 Merge branch 'master' into dev 2016-06-20 21:46:33 +02:00
Mario Vavti
17c5502330 missing backslash leading to wsod on xconfig changes 2016-06-20 21:45:15 +02:00
Andrew Manning
aa88837a31 Merge branch 'dev' into wiki 2016-06-20 13:28:50 -04:00
Andrew Manning
a3ec9f3940 Add formatted heading for revision comparison viewer 2016-06-20 13:27:05 -04:00
Andrew Manning
8cd9a1e4fc Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-20 13:07:29 -04:00
Andrew Manning
f4d9d34bbc Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-06-20 13:06:32 -04:00
Andrew Manning
20b4fc9198 Do not change active page commit until user reverts the page 2016-06-20 13:05:18 -04:00
Mario Vavti
e40112b40d Merge branch 'dev' into sabre32 2016-06-20 09:31:27 +02:00
redmatrix
cc09f9a7a5 Added many of the recent schema changes to the database schema documentation 2016-06-19 22:50:41 -07:00
redmatrix
4b505948f0 update the bbcode doc 2016-06-19 22:04:08 -07:00
redmatrix
3cf6f1f79c merge conflict 2016-06-19 21:47:04 -07:00
redmatrix
905374c86e experimental rtl support; this will probably require a fair bit of work. 2016-06-19 21:10:57 -07:00
redmatrix
953ca2c21e zot_revision should be string, not float 2016-06-19 19:15:26 -07:00
redmatrix
8b42834c3f recreate link from the merge kerfuffle 2016-06-19 19:13:23 -07:00
redmatrix
fb61c4fb34 Merge branch '1.8RC' 2016-06-19 19:12:33 -07:00
redmatrix
30841d9470 Don't use count() to check DB results 2016-06-19 18:57:56 -07:00
Mario Vavti
7a4efcf67f return something so we can make a conclusion 2016-06-19 20:34:38 +02:00
Mario Vavti
6e0eb532a5 Merge branch 'dev' into sabre32 2016-06-19 11:04:02 +02:00
redmatrix
bfaabfb7b5 hebrew hstrings.php was empty 2016-06-18 20:27:10 -07:00
redmatrix
4578649f75 hebrew hstrings.php was empty 2016-06-18 20:26:36 -07:00
redmatrix
b6324246ff hebrew hstrings.php was empty 2016-06-18 20:25:31 -07:00
redmatrix
53e4713932 hebrew update 2016-06-18 20:09:52 -07:00
root
76e11b46b7 hebrew translation 2016-06-18 20:03:38 -07:00
redmatrix
3dad4a9ff1 update the top level database doc, the individual schema pages are still out of date. 2016-06-18 19:57:44 -07:00
hubzilla
310f370b55 Merge pull request #426 from eduoda/master
When picktime is false, close date selector on date select
2016-06-19 12:45:47 +10:00
Oda
5b92922516 When picktime is false, close date selector on date select 2016-06-18 23:03:06 -03:00
redmatrix
dbb0a0283f schema changes needed for the caldav client bit 2016-06-18 15:33:47 -07:00
hubzilla
08f108e6cf Merge pull request #424 from BlaBlaNet/master
hebrew translation
2016-06-19 07:31:43 +10:00
root
5c947c7519 hebrew translation 2016-06-18 13:57:40 +00:00
Mario Vavti
178b440f05 Merge branch 'dev' into sabre32 2016-06-18 11:10:40 +02:00
redmatrix
755dd67ec7 changelog update for 1.8 2016-06-17 22:42:17 -07:00
redmatrix
99e8499722 changelog update for 1.8 2016-06-17 22:41:45 -07:00
redmatrix
2e7606f569 the text link to a thing will take you to the local thing page, both as a link for editing and as a destination in case there is no thing photo. If there's a photo, the photo link will take you to the thing URL. 2016-06-17 21:44:08 -07:00
redmatrix
22edd00211 "thing" always showing default url, not that supplied by the thing. 2016-06-17 21:26:25 -07:00
redmatrix
c81f6b9f6f "thing" always showing default url, not that supplied by the thing. 2016-06-17 16:28:36 -07:00
redmatrix
d0f0a99909 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-17 15:02:07 -07:00
redmatrix
2793086c0d 1. string update, 2. pretty print json blobs 2016-06-17 14:58:03 -07:00
Andrew Manning
80d3a831f3 Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-17 06:36:09 -04:00
Andrew Manning
961539258b Wiki page revision comparison tool with diff displayed in modal dialog. Leverages Diff class from http://code.stephenmorley.org/php/diff-implementation with license CC0 1.0 universal http://creativecommons.org/publicdomain/zero/1.0/legalcode 2016-06-17 06:33:39 -04:00
Mario Vavti
9749bbcedc Merge branch 'dev' into sabre32 2016-06-17 11:58:14 +02:00
Mario Vavti
aa5ac9dc3f only use height: auto for week and day view 2016-06-17 11:57:36 +02:00
Mario Vavti
0324bc5cf0 Merge branch 'dev' into sabre32 2016-06-17 10:04:27 +02:00
redmatrix
f6d7628254 core changes to better support media migrations 2016-06-16 20:16:39 -07:00
Andrew Manning
e5f4d80bbe Merge remote-tracking branch 'upstream/dev' into dev 2016-06-16 19:45:02 -04:00
redmatrix
aa77b04860 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-16 05:08:26 -07:00
Mario Vavti
5b479d63d6 Merge branch 'dev' into sabre32 2016-06-16 12:22:32 +02:00
Mario Vavti
8924f94d05 show month view in full height in fullscreen view 2016-06-16 12:21:59 +02:00
Mario Vavti
a873b7b6e8 mrge branch 'dev' into sabre32 2016-06-16 11:37:16 +02:00
Mario Vavti
7baa20d559 fix scrollbars 2016-06-16 11:36:51 +02:00
Mario Vavti
2b7f114c2d Merge branch 'dev' into sabre32 2016-06-16 11:22:52 +02:00
Mario Vavti
951bf5ec2e update 3rd party lib fullcalendar to version 2.7.3 2016-06-16 11:22:08 +02:00
Mario Vavti
28a7458e48 Merge branch 'dev' into sabre32 2016-06-16 10:26:47 +02:00
redmatrix
a2a87fec54 code comments 2016-06-15 22:36:00 -07:00
redmatrix
d457f11717 custom request methods for curl 2016-06-15 21:25:26 -07:00
redmatrix
bc5f73e6c3 provide a default for undefined languages 2016-06-15 20:51:55 -07:00
redmatrix
1dc35db1fe ignore case in language names and add 'js' as an alias for 'javascript' 2016-06-15 20:25:19 -07:00
redmatrix
427badcae9 improve readability of comments 2016-06-15 20:09:40 -07:00
hubzilla
e0b705fd54 Merge pull request #422 from anaqreon/wiki
Wiki rename page feature added. Bug fixes related to git commits.
2016-06-16 13:01:49 +10:00
redmatrix
854c23a751 This was the reason for the large line widths - an extra linefeed after each li element 2016-06-15 19:59:30 -07:00
redmatrix
fa48de33c2 provide syntax based [colour] highlighting on code blocks for popular languages. I'm not happy with the line height on the list elements but couldn't see where this was defaulted. This uses the syntax [code=xxx]some code snippet[/code], where xxx represents a code/language style - with about 18 builtins. 2016-06-15 19:44:15 -07:00
Andrew Manning
fc7c4e64ff Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-15 21:48:47 -04:00
redmatrix
d9aa16aa82 Merge branch '1.8RC' of https://github.com/redmatrix/hubzilla into 1.8RC_merge 2016-06-15 16:25:39 -07:00
redmatrix
976e32d3ae translate already imported system apps 2016-06-15 16:25:24 -07:00
redmatrix
476116a972 translate already imported system apps 2016-06-15 16:24:45 -07:00
Andrew Manning
f2dda646ec Merge remote-tracking branch 'upstream/dev' into dev 2016-06-15 19:15:47 -04:00
Mario Vavti
05ed20d336 Merge branch 'dev' into sabre32 2016-06-15 17:34:03 +02:00
jeroenpraat
b0476be36f All languages up to date as far as they are updated. Added Hebrew (I saw no RTL on my browser, but maybe that's a locale setting or else it's not yet implemented in HZ). Removed Esperanto and Czech (they where old ones from Friendica and are not on Transifex (yet)). 2016-06-15 17:26:44 +02:00
redmatrix
a005088228 Merge branch '1.8RC' of https://github.com/redmatrix/hubzilla into 1.8RC_merge 2016-06-15 05:30:19 -07:00
redmatrix
ef1c01d968 add new connection to default group when auto-accepted 2016-06-15 05:30:03 -07:00
redmatrix
47fc0c7958 add new connection to default group when auto-accepted 2016-06-15 05:28:16 -07:00
Jeroen van Riet Paap
a9f690260a Merge pull request #420 from phellmes/de20160615
Update DE translation strings
2016-06-15 13:53:02 +02:00
Andrew Manning
688171d016 Rename page feature added. Fixed bug in git commit function and other minor fixes. 2016-06-15 06:25:31 -04:00
phellmes
a16dcc877c Update DE translation strings 2016-06-15 12:12:18 +02:00
Mario Vavti
9a0dff08bc Merge branch 'dev' into sabre32 2016-06-15 08:42:51 +02:00
redmatrix
77dedf6648 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-14 20:31:10 -07:00
redmatrix
212d8b6cfd support cookie auth in Sabre DAV 2016-06-14 20:30:34 -07:00
hubzilla
9eb23a1208 Merge pull request #419 from anaqreon/wiki
Wiki context help translations IT and ES-ES
2016-06-15 10:06:08 +10:00
redmatrix
ccfd028919 readme for the module directory, also provide an undocumented way to reset the timestamp on connection photos to force a refresh without messing with the database directly. 2016-06-14 17:04:29 -07:00
Andrew Manning
e5a919c32e Fix Spanish wiki translation 2016-06-14 19:58:33 -04:00
Andrew Manning
eeaafe9f39 Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-14 19:56:04 -04:00
Andrew Manning
6430a232f8 Add Italian wiki context help translation 2016-06-14 19:55:31 -04:00
Mario Vavti
24569a18db css fix 2016-06-14 23:21:26 +02:00
Mario Vavti
5c458e9111 Merge branch 'dev' into sabre32 2016-06-14 09:42:43 +02:00
redmatrix
0ef2622621 some work to provide propagation and honouring of the item_notshown flag. 2016-06-13 22:09:22 -07:00
redmatrix
1ff9abe1b4 missing iconfig conversion 2016-06-13 21:16:36 -07:00
hubzilla
8e5948716e Merge pull request #418 from anaqreon/wiki
Wiki context help translations DE and ES-ES
2016-06-14 13:03:30 +10:00
redmatrix
1e68d4fb75 deprecate the item_id table - replace with iconfig. A possibly useful function in the iconfig class would be a search which takes a service id and type and uid, matches against an item and returns the iid. That could save a bit of code duplication. 2016-06-13 19:58:24 -07:00
Andrew Manning
1bec739195 Missing space in Spanish translation 2016-06-13 21:59:51 -04:00
Andrew Manning
025a7d2f0f Missing onclick attributes in German translation 2016-06-13 21:57:48 -04:00
Andrew Manning
ebf238be5d Move Spanish context help translation from es to es-es and make es a symlink to es-es 2016-06-13 21:47:05 -04:00
Andrew Manning
98484f0def Move Spanish context help translation from es to es-es and make es a symlink to es-es 2016-06-13 21:42:00 -04:00
Andrew Manning
892f061ad6 Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-13 20:48:57 -04:00
Andrew Manning
8bfb620a13 Add DE and ES-ES translations for wiki context help 2016-06-13 20:48:19 -04:00
Mario Vavti
b6d425838f css fixes 2016-06-13 17:19:49 +02:00
Mario Vavti
e963714ad6 Merge branch 'dev' into sabre32 2016-06-13 09:18:39 +02:00
hubzilla
6d4188f05e Merge pull request #417 from anaqreon/wiki
Wiki context help first draft
2016-06-13 12:10:20 +10:00
Andrew Manning
3e804757c1 Context help for wiki interface 2016-06-12 21:15:52 -04:00
Andrew Manning
cc43a49b6d Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-12 20:24:26 -04:00
hubzilla
b18b9464a4 Merge pull request #416 from anaqreon/embedphotos
Add embed photos button with album browser to new post editor
2016-06-13 10:15:09 +10:00
Andrew Manning
71d4f65cb2 Move javascript functions back to jot-header.tpl 2016-06-12 20:10:37 -04:00
Andrew Manning
b5933e9d44 Photo embed button with album browser works in new post editor. 2016-06-12 19:41:37 -04:00
redmatrix
7abfe716b4 DB schema issue with import 2016-06-12 16:35:17 -07:00
redmatrix
81b3c59711 DB schema issue with import 2016-06-12 16:34:27 -07:00
Andrew Manning
410f5389ae Apply purify_html to page content before preview and save to prevent JavaScript code injection. 2016-06-12 15:18:43 -07:00
hubzilla
290a14d29e Merge pull request #414 from anaqreon/1.8RC
Add filter to wiki content to prevent JavaScript code injection
2016-06-13 08:16:26 +10:00
Andrew Manning
a1183bf09a Merge remote-tracking branch 'upstream/dev' into embedphotos 2016-06-12 14:38:48 -04:00
Andrew Manning
e109abbef7 Apply purify_html to page content before preview and save to prevent JavaScript code injection. 2016-06-12 07:17:23 -04:00
Andrew Manning
43055e0199 Apply purify_html to page content before preview and save to prevent JavaScript code injection. 2016-06-12 07:14:12 -04:00
redmatrix
1789c3242a Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-11 15:29:25 -07:00
redmatrix
f41380de77 remove debugging 2016-06-11 15:28:52 -07:00
redmatrix
0e0a6f5f8d Work supporting issue #411, add an optional priority (int) as a second arg to head_add_js to affect the load ordering, larger numbered priorities will be included after lower numbered ones. Default priority is 0.Note that we treat main.js differently and always add main.js to the page last, regardless of any other
ordering.
2016-06-11 15:23:13 -07:00
Mario Vavti
ef95c68b4f Merge branch 'dev' into sabre32 2016-06-11 20:33:03 +02:00
Mario Vavti
0cada39c8a css fixes 2016-06-11 20:31:37 +02:00
Mario Vavti
bdbbe00bdf Merge branch 'dev' into sabre32 2016-06-11 20:12:41 +02:00
jeroenpraat
a1241daa41 es_ES and NL string for 1.8RC. Hopefully I'm doing it right. 2016-06-11 17:58:37 +02:00
jeroenpraat
1f43da2ade Merge branch '1.8RC' of https://github.com/redmatrix/hubzilla into 1.8RC 2016-06-11 17:54:26 +02:00
redmatrix
1614dbf6ae iconfig sharing not set correctly 2016-06-10 22:42:59 -07:00
redmatrix
96cd63cf1a iconfig sharing not set correctly 2016-06-10 22:41:58 -07:00
redmatrix
974ca9d526 move dev forward 2016-06-10 14:26:14 -07:00
Mario Vavti
86985b454f Merge branch 'dev' into sabre32 2016-06-10 12:22:01 +02:00
redmatrix
c55a7b5f36 changelog update 2016-06-10 03:16:15 -07:00
hubzilla
beb55235c6 Merge pull request #410 from anaqreon/wiki
Wiki module: first iteration
2016-06-10 20:03:08 +10:00
Mario Vavti
9d5d3a9468 Merge branch 'dev' into sabre32 2016-06-10 10:45:09 +02:00
redmatrix
cf415a4312 strings update 2016-06-10 01:18:52 -07:00
redmatrix
bb3d56a0b2 foreach: invalid argument 2016-06-09 22:07:27 -07:00
redmatrix
8f181bb188 change loglevel 2016-06-09 20:28:37 -07:00
redmatrix
135d84ba37 several "to-do" updates 2016-06-09 19:06:31 -07:00
redmatrix
77442dfcdc add safemode tool 2016-06-09 18:34:25 -07:00
redmatrix
ed597146fa Create the initial 1.8 changelog entry (subject to further changes) 2016-06-09 18:31:42 -07:00
Andrew Manning
7a242f829f Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-09 20:07:09 -04:00
Andrew Manning
7fc2b13fe6 Stashing changes. Not a functional state. 2016-06-09 20:06:36 -04:00
redmatrix
ee5372784e remove the automatic ajax page load on pgdn key; it can load content much faster than you can page and potentially lead to memory exhaustion. 2016-06-09 16:45:53 -07:00
redmatrix
0dcea87b99 namespace issue with openid reverse auth 2016-06-09 16:20:16 -07:00
redmatrix
d5d5d78e3a initial perms work 2016-06-09 16:16:56 -07:00
redmatrix
a10f5e9e06 allow an exclusion for transmitting hidden file activities. There may be a better way to do this, but it was pointed out recently that transmitting some hidden activities might cause a problem. I cannot locate the conversation at the moment to summarise the exact issue. 2016-06-09 16:11:58 -07:00
Mario Vavti
85e82e919e more style work 2016-06-09 22:05:52 +02:00
Mario Vavti
9b96fe66a6 Merge branch 'sabre32' of https://github.com/redmatrix/hubzilla into sabre32 2016-06-09 09:10:46 +02:00
Mario Vavti
11045b92fb Merge branch 'dev' into sabre32 2016-06-09 09:09:13 +02:00
redmatrix
2ad5010dc3 issue #59 2016-06-08 20:00:36 -07:00
redmatrix
40bba93a31 potential fix to hubzilla-addons issue 16 2016-06-08 19:34:11 -07:00
Andrew Manning
9410b63bbc Revised permissions checks across API and enabled collaborative editing using the write_pages per-channel permission. 2016-06-08 06:26:27 -04:00
Mario Vavti
4234c9a194 Merge branch 'dev' into sabre32 2016-06-08 12:04:45 +02:00
Andrew Manning
d43a814385 Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-08 05:41:13 -04:00
redmatrix
e46e7002a8 block random_profile from accessing sys channels 2016-06-07 22:55:24 -07:00
redmatrix
e6d20877b8 whitespace 2016-06-07 18:27:37 -07:00
redmatrix
5ef8199dae Finish the config family 2016-06-07 18:17:39 -07:00
Andrew Manning
e86e666c22 Javascript only allows saving a page if the content has changed. 2016-06-07 20:58:14 -04:00
Andrew Manning
cf180f6142 Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-07 20:43:49 -04:00
redmatrix
67665a8b9d slight alteration to the base description 2016-06-07 16:37:04 -07:00
redmatrix
a50e555515 'recent photos' query was buggered, also fix issue #163 by adding configurable sort order to the album widget - default is album name ascending 2016-06-07 16:23:14 -07:00
Mario Vavti
75b97cafb0 Merge branch 'dev' into sabre32 2016-06-07 09:43:14 +02:00
redmatrix
037cd74e8e rename admin/users to admin/accounts, provide sortable columns in account and channel summaries - issue #255 2016-06-06 19:44:22 -07:00
redmatrix
82a81cd01f new utility: util/safemode (on or off); requires util/addons 2016-06-06 16:34:10 -07:00
Mario Vavti
655290b022 Merge branch 'sabre32' of https://github.com/redmatrix/hubzilla into sabre32 2016-06-06 14:14:40 +02:00
Mario Vavti
b886a40471 Merge branch 'dev' into sabre32 2016-06-06 09:39:56 +02:00
redmatrix
c0d80a5828 adjust the autocomplete regex slightly to account for emoji names 2016-06-05 22:38:44 -07:00
redmatrix
adecd2960e move pconfig to static class 2016-06-05 22:18:17 -07:00
redmatrix
9afecaaffe We need a laugh icon more than we need a cry icon. 2016-06-05 20:16:33 -07:00
Andrew Manning
2af8105b46 Hide page history viewer when viewing sandbox 2016-06-05 21:14:30 -04:00
Andrew Manning
4528becf4c Remove debugging logger statements 2016-06-05 20:52:40 -04:00
Andrew Manning
d2a7f83bb5 Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-05 20:31:34 -04:00
Andrew Manning
b8b50bdb5a Custom commit message available. Improved history viewer and feedback from revert buttons. 2016-06-05 20:30:45 -04:00
redmatrix
4485142a25 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-06-05 17:01:03 -07:00
redmatrix
2a6afeb9a7 I don't know how to make this any clearer: "For these reasons we strongly recommend that you do NOT install addons from third-party repositories." 2016-06-05 16:59:45 -07:00
jeroenpraat
e2245446a3 Updating NL + es_ES strings 2016-06-06 01:18:18 +02:00
Andrew Manning
08a9553ccc Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-05 16:52:02 -04:00
Andrew Manning
0a3fbdd128 Basic page reversion implemented. The revert button on the history view replaces the editor text but does not save the page. 2016-06-05 16:32:03 -04:00
Mario Vavti
cfbd2fc85c Merge branch 'dev' into sabre32 2016-06-05 20:04:12 +02:00
redmatrix
dd6718c2cd provide a hover class for smiley emojis which renders them slightly larger on compatible devices when you single them out for inspection 2016-06-04 18:10:42 -07:00
redmatrix
c1a24d44a3 another switch of type and ttype 2016-06-04 17:17:48 -07:00
redmatrix
bf438f67e1 the :tone variants are messed up, remove them 2016-06-04 17:13:55 -07:00
redmatrix
81f6511d34 return of the project smilie 2016-06-04 17:09:37 -07:00
redmatrix
a6012af00d For emojis in posts, extend smilies and save a lot of duplication of effort 2016-06-04 17:06:12 -07:00
redmatrix
a0d339f208 short-term solution to emoji size issue - make them 32px from the sender 2016-06-04 15:53:30 -07:00
redmatrix
2c7ce20ccf cross-site encoding issue with tags 2016-06-04 15:04:14 -07:00
Andrew Manning
4bc4fd5b7e Page deletion implemented. Hide the delete button and disallow for Home page. 2016-06-04 18:00:32 -04:00
Andrew Manning
a92241d3cf Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-04 15:13:10 -04:00
Andrew Manning
344c293424 Wiki and page filenames are abstracted from their displayed names. Special characters do not seem to break things. 2016-06-04 15:12:04 -04:00
redmatrix
71cd6ef24b class object call 2016-06-04 05:01:15 -07:00
redmatrix
9b87a249b9 class functions not called with an object 2016-06-04 03:34:55 -07:00
redmatrix
b84f7cd37f class functions called incorrectly 2016-06-04 03:32:03 -07:00
Andrew Manning
b5d8443f59 Created three distinct names for wiki and page that are suitable for URL, HTML, and raw display. Implemented in new wiki POST activity only so far. 2016-06-04 06:26:41 -04:00
Andrew Manning
c08f428b5e Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-04 05:45:53 -04:00
redmatrix
20a79c7acf allow bbcode emojis (at least the single unicode character forms) 2016-06-03 22:00:53 -07:00
redmatrix
a4474b49cb make init static on master also 2016-06-03 20:22:20 -07:00
redmatrix
0333dca550 App::init() should be static 2016-06-03 19:46:48 -07:00
redmatrix
af4352adf2 need to set item_origin on locally created reactions so they propagate properly 2016-06-03 18:46:59 -07:00
redmatrix
1877df0e70 missed table rename in event query in mod_manage 2016-06-03 18:39:11 -07:00
redmatrix
a7e5e3d574 allow any (current) emoji to be displayed on any site, and provide a default list of reactions that can be over-ridden via configuration if a site doesn't like our choices or perhaps the ordering of our choices. 2016-06-03 18:13:21 -07:00
redmatrix
e81ac9e063 turn emoji ability into a feature so that either a member or the site admin can disable it. Default is enabled. 2016-06-03 16:04:54 -07:00
redmatrix
624f4641e2 missed an object -> obj conversion in prepare_body 2016-06-03 15:09:58 -07:00
redmatrix
dcba30a6aa strings 2016-06-03 14:52:00 -07:00
Mario Vavti
25aded6b9b Merge branch 'sabre32' of https://github.com/redmatrix/hubzilla into sabre32 2016-06-03 11:04:16 +02:00
Mario Vavti
8d6c2b5d4a Merge branch 'dev' into sabre32 2016-06-03 11:03:44 +02:00
Mario Vavti
29a0a11b7e some theming for emoji button 2016-06-03 11:03:01 +02:00
Mario Vavti
7582802f03 Merge branch 'dev' into sabre32 2016-06-03 09:40:37 +02:00
redmatrix
f8949ed5d1 restrict emoji reactions to the top level for now. 2016-06-02 22:12:56 -07:00
redmatrix
7ae376b6cd menu entries for basic emoji support. I could use a bit of help theming this. It may also be better rendered as a panel of buttons than a dropdown menu. Eventually we should probably allow the system admin to configure the emojis they want; as there are a large number. I only brought in a small collection that I thought would be most useful as post reactions. 2016-06-02 22:06:19 -07:00
redmatrix
390ce207db experimental emoji support 2016-06-02 20:31:34 -07:00
Andrew Manning
b93e398674 Merge remote-tracking branch 'upstream/dev' into wiki 2016-06-02 22:32:50 -04:00
Andrew Manning
b70c680964 Major corrections to access control and page construction. 2016-06-02 22:27:26 -04:00
redmatrix
f9075e2a2f some initial emoji reaction work 2016-06-02 18:42:51 -07:00
redmatrix
e596bf025b preserve app categories when updating a system app 2016-06-02 17:08:47 -07:00
redmatrix
4a3ec65409 adjust algorithm to ensure new system apps are installed. 2016-06-02 16:45:00 -07:00
redmatrix
0f1fcd9743 install system apps if a) they have never been installed, or b) if the app version changes 2016-06-02 16:38:15 -07:00
Mario Vavti
f23bdde464 Merge branch 'dev' into sabre32 2016-06-02 11:02:15 +02:00
redmatrix
05d9e1bee5 check all return values 2016-06-01 22:05:17 -07:00
redmatrix
a9d7acda27 the rest of the schema updates - WARNING: some third party plugins may fail; e.g. embedphotos and chess. $item['object'] is now $item['obj'] and $photo['type'] is $photo['mimetype'], $photo['scale'] is $photo['imgscale'] and $photo['data'] is now $photo['content']. There are a number of other changes, but these are the ones noted to cause issues with third-party plugins. The project plugins have been updated. Please note any new issues as this effort touched a lot of code in a lot of files. 2016-06-01 21:48:54 -07:00
Mario Vavti
b4eb9f2a11 Merge branch 'sabre32' of https://github.com/redmatrix/hubzilla into sabre32 2016-06-01 10:00:44 +02:00
Mario Vavti
c1039977f1 Merge branch 'dev' into sabre32 2016-06-01 09:15:56 +02:00
redmatrix
b1259876bf more db column renames 2016-05-31 21:45:33 -07:00
redmatrix
dfb6255f59 more removal of reserved words from DB schemas 2016-05-31 17:50:47 -07:00
redmatrix
00b4843425 provide a sort of mutex lock around db logging so it can't possibly recurse. Previous attempts to do something similar using other methods haven't worked out satisfactorily. 2016-05-31 16:16:54 -07:00
redmatrix
701acf59e2 don't remove missing hooks while update_r1169 is happpening - temp fix 2016-05-31 13:22:47 -07:00
Mario Vavti
380f65d309 Merge branch 'dev' into sabre32 2016-05-31 11:01:24 +02:00
Mario Vavti
316fee93f7 Merge branch 'dev' into sabre32 2016-05-31 10:59:11 +02:00
redmatrix
ca78374f30 remove unused tables 2016-05-30 22:41:45 -07:00
redmatrix
670e83b300 remove a bunch of unused stuff, some of which is orphaned and some which represents dead development efforts 2016-05-30 22:16:34 -07:00
redmatrix
44d3dadb03 don't update hubloc_connected any more often than 15 minutes. We don't require that level of granularity and the frequent writes are causing issues with the stability of that table. 2016-05-30 20:59:46 -07:00
redmatrix
9e9f2e13fe Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-30 19:49:15 -07:00
redmatrix
6602ff83dd start removing reserved words from database column names (this run: addon and hook) 2016-05-30 19:44:30 -07:00
Andrew Manning
8d284bab47 Created page history widget to dynamically fetch and display the git commit history for wiki pages. 2016-05-30 20:59:54 -04:00
redmatrix
490ab9e2c5 begin moving config to zotlabs. Leave procedural stubs for backward comaptibility 2016-05-30 16:42:29 -07:00
hubzilla
0757dbf07f Merge pull request #405 from git-marijus/dev
render code bbcode inline if there are no linebreaks in the text.
2016-05-31 09:07:22 +10:00
redmatrix
f35609d26c redundant dev line from an earlier modification causes issue #404 2016-05-30 13:25:58 -07:00
Andrew Manning
82ec40dd80 Merge remote-tracking branch 'upstream/dev' into wiki 2016-05-30 15:00:50 -04:00
Andrew Manning
a52cdcb241 Replaced wiki item record object field with ActivityStreams information. Wiki git repo path is stored in iconfig instead. 2016-05-30 14:59:33 -04:00
Mario Vavti
d1efb59fcd render code bbcode inline if there are no linebreaks in the text. 2016-05-30 16:12:48 +02:00
Mario Vavti
1523e116b9 Merge branch 'sabre32' of https://github.com/redmatrix/hubzilla into sabre32 2016-05-30 10:12:39 +02:00
Mario Vavti
90f2959076 Merge branch 'dev' into sabre32 2016-05-30 10:10:44 +02:00
Mario Vavti
6d4adfcedc Merge branch 'dev' into sabre32 2016-05-30 10:08:13 +02:00
redmatrix
f2ebe41a50 undefined function 2016-05-29 20:18:28 -07:00
Andrew Manning
8f0c3f0e9b Merge remote-tracking branch 'upstream/dev' into wiki 2016-05-29 21:45:54 -04:00
redmatrix
3b2679db29 fix remote_channel(), update php minversion requirement 2016-05-29 18:38:24 -07:00
Andrew Manning
4b350b9090 Fixed bug in access control. Hide new wiki/page buttons if not channel owner. 2016-05-29 21:23:56 -04:00
Andrew Manning
a3dfdd9d38 Remove Parsedown library files and remove references. 2016-05-29 20:44:28 -04:00
Andrew Manning
00d32f6b94 Only show wiki delete control if channel owner 2016-05-29 20:39:19 -04:00
Andrew Manning
fad27fc1e7 Hide page controls when not owner. Fixed some serious access control issues. 2016-05-29 20:16:17 -04:00
Andrew Manning
3e6af5c876 Hacked Parsedown and Markdown to add class inline-code to <code> blocks for proper inline code rendering. Stopped using Parsedown even though Markdown is slower, hence extra delay when previewing pages. 2016-05-29 17:06:45 -04:00
Andrew Manning
75b169f391 Fixed bug where page file was not loaded because of urlencoding/urldecoding 2016-05-29 13:50:32 -04:00
Andrew Manning
df7772e301 Home page create with new wiki. URL redirects here when no page given. Fixed bug with author in wiki item table record. 2016-05-29 13:33:52 -04:00
Andrew Manning
63a97ff6fc Git commit made for the page edits when the page is saved. 2016-05-29 10:18:26 -04:00
Mario Vavti
cac6cef495 use composer to install sabre32 2016-05-29 10:58:11 +02:00
Mario Vavti
aab9766c53 missed some files 2016-05-29 00:33:28 +02:00
Andrew Manning
ab54bf5149 Wiki pages can be saved. 2016-05-28 15:11:19 -04:00
Andrew Manning
55b587002e Merge remote-tracking branch 'upstream/dev' into wiki 2016-05-28 14:12:53 -04:00
Andrew Manning
819683a073 Show page content by default. Hide page controls where appropriate. Fix sandbox text format. 2016-05-28 14:11:36 -04:00
Andrew Manning
7393dccde8 Page content is loaded from the file on disk 2016-05-28 12:33:07 -04:00
Mario Vavti
66effbfe08 upgrade to sabre32 2016-05-28 17:46:24 +02:00
Andrew Manning
ae94e8a855 Wiki page list links work. File content is not yet loaded into the editor. Removed some logger calls. 2016-05-28 07:42:18 -04:00
Andrew Manning
f884fa6678 Wiki page list is fetched and the page widget is updated 2016-05-28 07:17:42 -04:00
redmatrix
ac4688eac0 allow objs to represent inventory 2016-05-27 23:57:47 -07:00
Andrew Manning
4691c3ec01 Add new page to wiki and redirect to editor page. 2016-05-27 22:19:05 -04:00
Andrew Manning
ca78ebce6d Check if wiki exists and redirect if it does not 2016-05-27 20:37:37 -04:00
Andrew Manning
97e6b7c4ba Wiki deletion works 2016-05-27 20:20:33 -04:00
redmatrix
ab6eb1c4b2 strings update 2016-05-27 16:11:58 -07:00
redmatrix
0919c1eb61 check for session before querying session vars 2016-05-27 16:09:44 -07:00
Andrew Manning
d554681174 Merge remote-tracking branch 'upstream/dev' into wiki 2016-05-27 06:35:15 -04:00
redmatrix
551cf8ee94 link to hubchart site for site detail on pubsites page 2016-05-26 19:40:16 -07:00
redmatrix
61304d80d2 track down some issues from the application logs 2016-05-26 18:45:47 -07:00
redmatrix
1bce285eca don't need quite so many backslashes 2016-05-26 17:51:59 -07:00
redmatrix
096fdfc61b consolidate all the sys_boot functionality that is common between the web server and the cli daemon manager. Get rid of yet another global variable ($default_timezone) whilst doing so. 2016-05-26 16:33:01 -07:00
redmatrix
8e4889bdf1 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-26 13:22:29 -07:00
redmatrix
7b91e551c4 kill off mcrypt 2016-05-26 13:21:43 -07:00
Mario Vavti
9d7abd58ac another typo 2016-05-26 14:37:30 +02:00
Mario Vavti
24360fd191 check if $addonDir is a dir to silence warning if it does not exist 2016-05-26 14:33:10 +02:00
Mario Vavti
9017dcd0fd typo 2016-05-26 14:23:17 +02:00
redmatrix
30d0f21079 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-25 21:32:40 -07:00
redmatrix
d78bc12cbe update to the bug doco 2016-05-25 21:32:13 -07:00
hubzilla
2a9c1db0c9 Merge pull request #402 from git-marijus/dev
another try on #385 - replace sabres restrictive CSP with what we do in boot.php
2016-05-26 14:25:48 +10:00
redmatrix
4716627453 run background/daemon tasks at approximately 4 hour intervals from web accesses if they aren't being run otherwise. This ensures they run, although perhaps a bit infrequently; even if unconfigured. This is not suitable for a production site, but may be acceptable for small single person hubs and test sites. The 'cron warning email' now means that background processes are totally borked; probably due to a fascist hosting provider that has blocked process execution. 2016-05-25 21:10:13 -07:00
redmatrix
2f64684299 some event fixes, also change jquery-textcomplete to un-minified since the minified version appears to require a mapping file and causes a lot of server fetch errors trying to load it. 2016-05-25 20:06:21 -07:00
redmatrix
66b6f8c0ff app rendering issues, typo in class name and could not find icon 'fa-arrow-circle-o-down-alt'; using 'fa-arrow-circle-o-down' instead 2016-05-25 17:30:15 -07:00
redmatrix
e559f8b6a1 duplicate daemon run of cronhooks 2016-05-25 16:48:32 -07:00
redmatrix
0d8dcdbbc9 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-25 13:46:55 -07:00
redmatrix
da19ac98dd Just set it and forget it. 2016-05-25 13:46:19 -07:00
Mario Vavti
45568bf097 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-05-25 14:32:17 +02:00
Mario Vavti
9908a7193a remove the add others button for now - after some research it turned out not beeing so useful 2016-05-25 14:31:58 +02:00
Mario Vavti
929d33fb22 another try on #385 - replace sabres restrictive CSP with what we do in boot.php 2016-05-25 14:18:41 +02:00
redmatrix
a3e617987f hubzilla is not a legal entity. the hubzilla community encompasses a group of people who are in fact legal entities. 2016-05-25 01:59:49 -07:00
redmatrix
c37eaff263 require token signatures in zot_refresh, also move channel specific stuff into include/channel.php from include/connections.php 2016-05-24 23:05:00 -07:00
redmatrix
80f2ba640e code cleanup 2016-05-24 20:49:23 -07:00
redmatrix
f9a295a236 Add space between project name and server type 2016-05-24 19:25:10 -07:00
redmatrix
516c43ba15 more work associated with DBA and index.php shuffle 2016-05-24 17:54:45 -07:00
redmatrix
84ba6393ad relocate index and db 2016-05-24 16:36:55 -07:00
Andrew Manning
e00b8a7082 Delete wiki (in progress) 2016-05-24 06:15:42 -04:00
redmatrix
29ba891809 moved enotify 2016-05-24 01:25:13 -07:00
redmatrix
25357b208a Clarify the privacy rights of commenters, as this can be contentious across the policies of different distributed communication systems. 2016-05-23 16:21:44 -07:00
redmatrix
80b422bdbe typo 2016-05-23 13:49:54 -07:00
redmatrix
1215638540 remove some doxygen files that leaked into /doc 2016-05-22 23:04:14 -07:00
redmatrix
bbc71343bd change the signed token format. We don't folks to be able to submit random text for signing by us, as they could then use these to generate known signatures. 2016-05-22 22:44:13 -07:00
redmatrix
a1aa3d9061 Can't use "use x as y" aliases in callback function declarations 2016-05-22 22:08:01 -07:00
redmatrix
1aa3051e97 move chatroom stuff to zlib 2016-05-22 20:54:52 -07:00
redmatrix
20f444f5f2 add missing file 2016-05-22 19:26:21 -07:00
redmatrix
2d06663490 move apps to zlib 2016-05-22 19:25:27 -07:00
redmatrix
5e0698ba87 turn the oft-repeated block_public ... check into a function observer_prohibited() 2016-05-22 17:52:30 -07:00
redmatrix
d7d347469c Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-22 16:57:46 -07:00
redmatrix
de006771c7 renamed include files identity.php (channel.php) and Contact.php (connections.php) 2016-05-22 16:54:30 -07:00
jeroenpraat
b4e5d303b5 Update NL + ES_ES 2016-05-22 23:17:06 +02:00
Andrew Manning
a36bef7979 List of wikis populates with links according to observer permissions. 2016-05-21 21:55:09 -04:00
redmatrix
2fdd148598 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-21 18:21:35 -07:00
redmatrix
3dc131757d include new finger backend 2016-05-21 18:21:04 -07:00
redmatrix
1cb311cef9 finish updating zot_finger instances 2016-05-21 18:18:33 -07:00
redmatrix
ed56b6e67b first cut at zot-finger request signatures 2016-05-21 18:02:14 -07:00
Andrew Manning
049147a9d7 Successful new wiki git repo and item table record 2016-05-21 19:02:23 -04:00
hubzilla
5c1f23b61a Merge pull request #400 from anaqreon/plugin-repo-path
Plugin repo path
2016-05-22 07:40:20 +10:00
hubzilla
4d4e49f4d8 Merge pull request #399 from phellmes/de20160521
Update DE translation strings
2016-05-22 07:39:47 +10:00
Andrew Manning
5f2baa59f5 Forgot some templates 2016-05-21 15:07:27 -04:00
Andrew Manning
c6aa42773a Trying to fix wiki branch starting fresh from dev 2016-05-21 14:56:42 -04:00
Andrew Manning
7a526fa8a9 Temp repo folder error message correction 2016-05-21 12:58:05 -04:00
Andrew Manning
598baa1b32 Moved git repository storage to store/[data]/git to avoid collision with a channel named git. Fixed bug where temp repo folder was never created. 2016-05-21 12:55:17 -04:00
phellmes
ef9b42aeb3 Update DE translation strings 2016-05-21 16:20:19 +02:00
Mario Vavti
4979a45120 revert fix for #385 2016-05-21 15:14:33 +02:00
Mario Vavti
b66bacff9f possible better fix for #385 2016-05-21 14:52:07 +02:00
Mario Vavti
9480e9b68b possible fix for #385 2016-05-21 14:34:01 +02:00
redmatrix
bf05012150 relocate the (unused currently) protocol driver 2016-05-20 23:12:06 -07:00
redmatrix
d8ace38041 rework the conversation object stuff at a high level - still needs a bit of refactoring 2016-05-20 22:52:47 -07:00
redmatrix
bc20cf9fa3 remove redundant include 2016-05-20 22:16:57 -07:00
redmatrix
019250eff8 consolidate include/*_selectors.php (not touching acl_selectors for the moment, as it will likely end up with a different disposition) 2016-05-20 22:13:20 -07:00
redmatrix
ac095c89f1 code comments 2016-05-20 19:14:49 -07:00
redmatrix
f4da365abd move template stuff to zotlabs/render 2016-05-20 19:11:14 -07:00
redmatrix
b2f0d2d085 cleanup proc_run after messing it up with debugging yesterday 2016-05-20 17:44:26 -07:00
redmatrix
aefeda8c41 recurse one more level of array when processing args 2016-05-20 01:45:29 -07:00
redmatrix
fdece3b102 add some backtrace to find the issue 2016-05-20 01:33:34 -07:00
redmatrix
cae380f068 case issue 2016-05-20 01:21:19 -07:00
redmatrix
3aa6e96904 update the installation text for the cron setup 2016-05-19 22:59:25 -07:00
redmatrix
a97e7b2758 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-19 22:48:58 -07:00
redmatrix
2cda18f354 remove test file 2016-05-19 22:48:32 -07:00
redmatrix
2e83c17e2d roll minor version, change example text 2016-05-19 22:47:20 -07:00
redmatrix
f228bf4555 typo uncovered during tests 2016-05-19 22:33:01 -07:00
redmatrix
a2cec8899a daemon conversion continued... 2016-05-19 22:26:37 -07:00
redmatrix
014168a29b cleanup of daemon infrastructure 2016-05-19 21:32:19 -07:00
redmatrix
39bc0664a7 Separate cron into periodic components and use that as the main interface for scheduled tasks instead of the quaint 'poller'. 2016-05-19 21:22:04 -07:00
redmatrix
853322e7d2 don't try to deliver empty hashes 2016-05-19 20:48:40 -07:00
redmatrix
9cb1ac3de5 daemon master: create some compatibility code 2016-05-19 20:36:32 -07:00
redmatrix
5b2474238e first phase of daemon refactoring 2016-05-19 19:42:45 -07:00
hubzilla
3c5cb15432 Merge pull request #397 from git-marijus/dev
provide an acl select option for only me
2016-05-20 11:39:44 +10:00
redmatrix
6e7d7c5017 minor 2016-05-19 16:48:10 -07:00
Mario Vavti
1f2bd00d93 whitespace 2016-05-19 23:39:05 +02:00
Mario Vavti
c7cad6ab60 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-05-19 23:35:48 +02:00
Mario Vavti
0f5eb65210 provide an acl select option for only me 2016-05-19 23:35:19 +02:00
hubzilla
fc239cb8a2 Merge pull request #395 from anaqreon/plugin-repo-ui
Plugin repo ui
2016-05-20 06:09:12 +10:00
hubzilla
3fe7bd8bcc Merge pull request #396 from Treer/permissions
fix permission string
2016-05-20 06:08:51 +10:00
Treer
6b69184554 fix permission string 2016-05-19 22:37:21 +10:00
Andrew Manning
d5ca889cf5 Replace text strings for translation support 2016-05-19 07:09:13 -04:00
Andrew Manning
062cb77539 Merge remote-tracking branch 'upstream/dev' into plugin-repo-ui 2016-05-19 07:04:36 -04:00
Andrew Manning
b55e2776cc Improved plugin repo management UI in admin/plugins 2016-05-19 07:03:42 -04:00
redmatrix
50d1d06b03 issue #391 - htmlspecialchars_decode before firing up jot, which re-encodes 2016-05-19 00:56:51 -07:00
redmatrix
93a7df5a1b one more text clarification 2016-05-18 22:57:23 -07:00
redmatrix
905432c7ae text clarifications 2016-05-18 22:53:43 -07:00
redmatrix
3355210878 explain what we're doing and where we're going with this. 2016-05-18 22:03:43 -07:00
redmatrix
ada26dd2cb This explains it all. Don't set the domain when creating a cookie. You'll get a wildcard and sessions will break if you have multiple domains running hubzilla (or any php basic session based code). 2016-05-18 21:00:31 -07:00
redmatrix
f4b31dcb3a Document what I know about the session regeneration issue. I'm really tired of fighting this darn thing. Sessions and cookies need to work. 2016-05-18 20:36:03 -07:00
hubzilla
7abb214eaf Merge pull request #394 from anaqreon/plugin-link
Link new plugins when updating repos via admin/plugins
2016-05-19 12:17:19 +10:00
Andrew Manning
77eb9bcfa0 Link new plugins when updating repos via admin/plugins 2016-05-18 21:32:23 -04:00
redmatrix
c17b47518d comment out session_regenerate until we get this sorted 2016-05-18 17:55:22 -07:00
redmatrix
1f7e6cae82 Revert "Revert "yet more session work""
This reverts commit 37d14f3a1d.
2016-05-18 17:03:54 -07:00
redmatrix
37d14f3a1d Revert "yet more session work"
This reverts commit 51edd472c2.
2016-05-18 17:02:46 -07:00
redmatrix
166d63ff60 missing close tag 2016-05-18 16:31:12 -07:00
redmatrix
d38851023e provide server role on pubsites page 2016-05-18 16:28:51 -07:00
hubzilla
e35bd5d251 Merge pull request #393 from git-marijus/dev
only show $showall_origin if permission_role is custom. it does not m…
2016-05-19 06:28:54 +10:00
Mario Vavti
c77732b8ed only show $showall_origin if permission_role is custom. it does not make much sense otherwise since the member is merely using a preset of permissions. 2016-05-18 21:23:24 +02:00
redmatrix
16f79b70e4 experimental PDO DBA driver 2016-05-17 22:32:49 -07:00
redmatrix
43c2b22fca cli utilities - argc and argv reversed. Not functionally incorrect since it was consistent but aesthetically incorrect. 2016-05-17 19:49:21 -07:00
hubzilla
9a64c6b9f7 Merge pull request #389 from sasiflo/dev_sasiflo_sync
Synchronization: Directory creation on sync import corrected.
2016-05-18 12:16:20 +10:00
redmatrix
20cb4130d4 support work for a long-term fix for issue #390, essentially one can specify a theme:schema string anywhere a theme is input. It will be honoured unless an existing schema setting over-rides this behaviour. This should also be backward compatible but the theme selection code has been cleaned up slightly and there may be subtle differences in behaviour after this commit. On my site this required a page refresh as the first page load after this change was a bit confused. 2016-05-17 17:46:30 -07:00
sasiflo
bfbe6c1660 Synchronization: Directory creation on sync import corrected. 2016-05-17 12:27:15 +02:00
redmatrix
51edd472c2 yet more session work 2016-05-16 22:01:33 -07:00
redmatrix
1977ab35c0 remove the app_menu hook - no longer used anywhere in core. Several addons still hook into it, but we can remove these over time. 2016-05-16 21:39:37 -07:00
redmatrix
296957b5b5 minor version roll 2016-05-16 19:39:08 -07:00
redmatrix
0d04a1221a issue #386 (master) 2016-05-16 19:38:38 -07:00
redmatrix
6ac6537f10 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-16 19:24:03 -07:00
redmatrix
883b1ff513 an issue related to #386 2016-05-16 19:23:42 -07:00
hubzilla
de1527eba8 Merge pull request #388 from phellmes/de20160516
Update DE translation strings
2016-05-17 10:29:53 +10:00
redmatrix
2dcedd6951 more work on sessions and cookies, as some anomalies appeared in caldav and firefox which suggested deeper issues 2016-05-16 17:07:39 -07:00
redmatrix
c8322e89c6 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-16 13:47:04 -07:00
redmatrix
18a9831cd3 restrict static to the one function that requires it 2016-05-16 13:46:35 -07:00
jeroenpraat
9f77180af8 Dutch and Spanish Spanish strings, and some schema-bits 2016-05-16 16:43:14 +02:00
phellmes
0bd4939695 Update DE translations strings 2016-05-16 15:11:53 +02:00
redmatrix
605c05fc8b changes to session for cdev compatibility 2016-05-16 02:03:15 -07:00
redmatrix
fa3aed4e59 updated the addons list - Andrew might want to add his repo/repos and addons to this page 2016-05-15 22:37:00 -07:00
redmatrix
217db8f9b2 provide tools to extract a pdo constructor 2016-05-15 19:16:55 -07:00
redmatrix
a0dd03ea0e be specific 2016-05-15 17:56:13 -07:00
redmatrix
894114bfbd be a bit more precise 2016-05-15 17:54:25 -07:00
redmatrix
90353d90dc Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-05-15 13:22:48 -07:00
redmatrix
c9ce5664d4 roll minor version due to change 2016-05-15 13:22:22 -07:00
redmatrix
e8ad16cf2a issue #387 2016-05-15 13:20:58 -07:00
redmatrix
c3090d5480 issue #387 2016-05-15 13:20:17 -07:00
jeroenpraat
f48aee5975 stupid git 2016-05-15 09:12:24 +02:00
jeroenpraat
60f6b827f4 the other way around 2016-05-15 09:09:45 +02:00
Manuel Jiménez Friaza
f05b4637b9 Another updated context help es-es 2016-05-14 23:41:49 -07:00
redmatrix
fffeca59d0 Merge pull request #382 from mjfriaza/dev
Another updated contextual help in Spanish
2016-05-15 16:38:14 +10:00
redmatrix
b14dd0e066 issue #383 2016-05-14 21:05:24 -07:00
redmatrix
ec81ef7b8d issue #383 2016-05-14 21:04:19 -07:00
redmatrix
e02c658eb5 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-14 18:36:47 -07:00
redmatrix
0800bd1e19 we don't need to force case conversion on anything but the plugin name 2016-05-14 17:30:06 -07:00
redmatrix
0503b11840 allow addon autoloaders to specify absolute namespace classes starting with \ 2016-05-14 17:24:50 -07:00
redmatrix
b497faee27 Allow plugins to define autoloaded classes - a class such as Foobar\Class will load addon/foobar/Class.php and also Foobar\Category\Class.php will load addon/foobar/Category/Class.php 2016-05-14 17:18:51 -07:00
Manuel Jiménez Friaza
7ee31276f5 Another updated context help es-es 2016-05-14 12:47:28 +02:00
redmatrix
5897f62fa9 Merge pull request #381 from anaqreon/chat-notify
Enable options for chat notifications, with optional audio. Notify fo…
2016-05-14 18:32:24 +10:00
Andrew Manning
0baab50191 Enable options for chat notifications, with optional audio. Notify for member entering room and incoming messages. 2016-05-13 21:47:37 -04:00
redmatrix
0db1594f95 Merge pull request #380 from git-marijus/dev
instead of radio buttons use select to choose between public and custom selection
2016-05-14 08:11:51 +10:00
Mario Vavti
1e00fa79b3 change wording restricted -> custom selection and add a label to the select 2016-05-13 17:38:50 +02:00
Mario Vavti
573dea42d0 instead of radio buttons use select to choose between public and restricted acl. if restricted is selected acl is set to default. if there is no default acl will be set to self. if public is selected acl-list will be hidden and acl-info is visible. 2016-05-13 16:22:43 +02:00
redmatrix
269055e71c strings update 2016-05-13 00:27:38 -07:00
redmatrix
2f222546da Comanche: provide a variable '$region' which can be used within a layout to make content aware of where it is on the page. For instance this can be passed as a variable to a widget and trigger either a vertical or horizontal layout depending on which region it is assigned to. 2016-05-12 21:18:34 -07:00
redmatrix
522fec5763 split off feed handling stuff from include/items 2016-05-12 20:21:04 -07:00
redmatrix
f2fc7d25c5 remove the rarely if ever used filter_insecure() function. We will provide this functionality in other ways. 2016-05-12 20:02:16 -07:00
redmatrix
2d79e75788 SECURITY: edited comment to private post loses privacy info. Not visible in stream but may be visible in feeds 2016-05-12 16:51:20 -07:00
redmatrix
781716277b SECURITY: a comment to a private post that has been edited (the comment has been edited) loses its privacy settings. This comment isn't visible in the stream but may be visible in feeds. 2016-05-12 16:47:03 -07:00
redmatrix
9f57bfb5df update std_version 2016-05-12 16:13:29 -07:00
redmatrix
4d00c48026 back merge 2016-05-12 16:11:38 -07:00
redmatrix
8fe8341d93 Merge pull request #379 from mjfriaza/dev
Updated contextual help in Spanish
2016-05-13 09:08:52 +10:00
redmatrix
57273db8a6 Merge pull request #378 from anaqreon/plugin-init
Create store/git/sys/extend/addon directory and link if it does not e…
2016-05-13 09:08:30 +10:00
Manuel Jiménez Friaza
bc9f88f3f9 Updated contextual help in Spanish 2016-05-12 19:56:05 +02:00
Andrew Manning
70d413ab04 Create store/git/sys/extend/addon directory and link if it does not exist in all plugin repo GUI POST actions 2016-05-12 06:49:24 -04:00
3357 changed files with 184309 additions and 208834 deletions

2
.gitignore vendored
View File

@@ -14,6 +14,8 @@
*.rej
# OSX .DS_Store files
.DS_Store
# version scripts (repo master only)
.version*
Thumbs.db

View File

@@ -27,9 +27,9 @@ Software
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
+ Log on to your new debian (server)
- apt-get install git
- mkdir -p /var/www/html
- cd /var/www/html
- git clone https://github.com/redmatrix/hubzilla.git .
- mkdir -p /var/www
- cd /var/www
- git clone https://github.com/redmatrix/hubzilla.git html
- cp .homeinstall/hubzilla-config.txt.template .homeinstall/hubzilla-config.txt
- nano .homeinstall/hubzilla-config.txt
- Enter your values there: db pass, domain, values for dyn DNS

View File

@@ -513,7 +513,7 @@ END
fi
# run letsencrypt.sh
#
./letsencrypt.sh --cron
./letsencrypt.sh --cron --config $le_dir/config.sh
}
function configure_apache_for_https {
@@ -668,45 +668,6 @@ function rewrite_to_https {
service apache2 restart
}
function install_owncloud {
if [ -z "$owncloud" ]
then
print_info "Do not install owncloud"
return 0
fi
if [ -f /etc/apt/sources.list.d/owncloud.list ]
then
print_info "owncloud is already installed and is left untouched"
return 0
fi
print_info "installing owncloud..."
# add the repository key to apt
wget -nv https://download.owncloud.org/download/repositories/stable/Debian_8.0/Release.key -O Release.key
apt-key add - < Release.key
# add the repository and install from there
sh -c "echo 'deb http://download.owncloud.org/download/repositories/stable/Debian_8.0/ /' >> /etc/apt/sources.list.d/owncloud.list"
apt-get update
nocheck_install "owncloud"
chown -R www-data:www-data /var/www/owncloud/
# set strong permissions
ocpath='/var/www/owncloud'
htuser='www-data'
htgroup='www-data'
rootuser='root' # On QNAP this is admin
find ${ocpath}/ -type f -print0 | xargs -0 chmod 0640
find ${ocpath}/ -type d -print0 | xargs -0 chmod 0750
chown -R ${rootuser}:${htgroup} ${ocpath}/
chown -R ${htuser}:${htgroup} ${ocpath}/apps/
chown -R ${htuser}:${htgroup} ${ocpath}/config/
chown -R ${htuser}:${htgroup} ${ocpath}/data/
chown -R ${htuser}:${htgroup} ${ocpath}/themes/
chown ${rootuser}:${htgroup} ${ocpath}/.htaccess
chown ${rootuser}:${htgroup} ${ocpath}/data/.htaccess
chmod 0644 ${ocpath}/.htaccess
chmod 0644 ${ocpath}/data/.htaccess
}
# This will allways overwrite both config files
# - internal disk
# - external disk (LUKS + ext4)
@@ -769,11 +730,11 @@ echo "#" >> /var/www/$hubzilladaily
echo "echo \" \"" >> /var/www/$hubzilladaily
echo "echo \"+++ \$(date) +++\"" >> /var/www/$hubzilladaily
echo "echo \" \"" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - renew certificat if 30 days old...\"" >> /var/www/$hubzilladaily
echo "bash /var/www/letsencrypt/letsencrypt.sh --cron" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - renew certificat...\"" >> /var/www/$hubzilladaily
echo "bash $le_dir/letsencrypt.sh --cron --config $le_dir/config.sh" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "# stop hubzilla" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - stoping apaache and mysql...\"" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - stoping apache and mysql...\"" >> /var/www/$hubzilladaily
echo "service apache2 stop" >> /var/www/$hubzilladaily
echo "/etc/init.d/mysql stop # to avoid inconsistancies" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
@@ -939,7 +900,6 @@ configure_apache_for_https
check_https
install_hubzilla
rewrite_to_https
# install_owncloud # deprecated
install_rsnapshot
configure_cron_daily
install_cryptosetup

142
CHANGELOG
View File

@@ -1,3 +1,145 @@
Hubzilla 1.12
- extensible permissions so you can create a new permission rule such as "can write to my wiki" or "can see me naked".
- guest access tokens can do anything you let them, including create posts and administer your channel
- ACLs can be set on files and directories prior to creation.
- ACL tool can now be used in multiple forms within a page
- a myriad of new drag/drop features (drop files or photos into /cloud or a post, or drop link into a post or comment, etc.)
- multiple file uploads
- improvements to website import
- UNO replaced with extensible server roles
- select bbcode elements (such as baseurl) supported in wiki pages
- addons:
Diaspora Protocol - additional updates to maintain compatibility with 0.6.0.0 and stop showing likes as wall-to-wall comments (except when the liker does not have any Diaspora protocol ability)
Cdav - continued improvements to the web UI
Pong - the classic pong game
Dfedfix - removed, no longer needed
Openid - moved from core to addon
- bugfixes
unable to delete privacy groups
weird display interaction with code blocks and escaped base64 content containing 8 - O
workaround WordPress oembeds which are almost completely javascript and therefore filtered
restrict oembed cache url to 254 chars to avoid spurious failures caching google map urls
"Page not found" appeared twice
birthdays weren't being automatically added to event calendar
some iCal entries had malformed descriptions
Hubzilla 1.10
Wiki:
Lots of enhanced functionality, usability improvements, and bugfixes from v1.8
Turned into an optional feature (default on) but disabled in UNO
Sync:
Items are now relocated (links patched) when syncing to clones
Access Tokens:
New feature - allows members to create access controlled guest logins and create/share 'dropbox' style links to protected resources.
UI:
Use icons instead of iconic text constructs
Only request geolocation permission when creating a post, not on page load
provide 'redeliver' option on Delivery Report page for when things really stuff up
CalDAV/CardDAV management pages with heaps of functionality
Lib:
z_fetch_url() updated to accept different request methods and request bodies
item_store(), item_store_update() now return the stored items
vcard microformat changes to remain spec compliant
microformat meta tags added to post/comments
AbConfig API changed to use channel_id rather than channel_hash, which was overly complicated to use
SuperCurl class added to provide a framework for re-use of obscure CURL options
Allow absolute links to CSS/JS files on CDN
Add Let'sEncrypt intermediate cert to lib in case you forget to install it on the server
Update fullcalendar and jquery (3.1) libs
Update sabre/dav to 3.2.0
Change content export from a month/year system to begin/end
Use streaming I/O for delivering large photos
Allow multiple App description files in a single plugin directory
optimise a couple of troublesome/inefficient SQL queries
avoid sending clone sync packets to dead sites
Resolved Issues:
channel home page not providing content to clients with javascript disabled
Replace '@' obfuscation with html entity rather than the unicode look-alike
xchan_query() failing to detect duplicates, resulting in inefficient queries
issues with 'use existing photo' for profile photo
layout editor "list all layouts" returned empty
oembed - better detect video file URLs so they aren't loaded into memory.
handcrafted bbcode tables could end up with way too much whitespace due to CRLF translation
refresh permissions whitescreen in 1.8
force immediate profile photo update on local site
regression: 'save bookmarks' post action missing
Hubzilla 1.8
Administration:
Cleanup and resolve some edge cases with addon repository manager
Provide sort field and direction on all fields of account and channel administration tables
Rename 'user' administration to account administration to reflect its true purpose
'safemode' tool to quickly disable and re-enable addons during a hypothetical upgrade crisis
Security:
Edited comments to private posts could lose their privacy settings under some circumstances
Provide zot-finger signatures to prevent a possible but rare exploit involving DNS spoofing and phishing
ACL selections:
Various improvements to the ACL editor to further simplify the concepts and make it more intuitive
Chat:
Notifications of chatroom activity using standard browser notification interfaces.
Themes:
Allow a theme:schema string to represent a valid theme name. This fixes issues with setting schemas on site themes.
Pubsites:
Show server role (identify UNO or basic sites as opposed to hubzilla pro) and link to statistics
Documentation:
Clarify privacy rights of commenters w/r/t conversation owners, as this policy is network dependent.
Wiki (Git backed):
Brand new feature. We'll call it experimental until it has undergone a bit more testing.
Account Cloning:
Regression on clone channel creation created a new channel name each time.
New issue (fixed) with directory creation on cloned file content
Content Rendering:
Add inline code (in addition to the existing code blocks) to BBcode
Add emoji reactions
Add emojis as extended smilies with auto-complete support
Emoji added as feature so it can be enabled/disabled and locked
Ability to configure the standard reactions available on a site basis
Disable 'convenience' ajax autoload on pgdn key, as it could lead to premature memory exhaustion
Photos:
Change album sort ordering, allow widgets and plugins to define other orderings
Apps:
Synchronise app list with changes to system apps
Preserve existing app categories on app updates/edits
Regression: fixed translated system app names
Architecture:
Provide autoloaded class files and libraries for plugins.
Further refactoring of session driver to sort out some cookie anomolies
Experimental PDO database driver
Creation of Daemon Master class and port all daemon (background task) interfaces to use it
Create separate class for each of 'Cron', 'Cron daily', and 'Cron weekly'.
Always run a Cron maintenance task if not run in the last four hours
Refactor the template classes
Refactor the ConversationItem mess into ThreadItem and ThreadStream
Refactor Apps, Enotify, and Chat library code
Refactor the various Config libraries (Config, PConfig, XConfig, AConfig, AbConfig, and IConfig)
Created WebServer class for top level
Remove mcrypt dependencies (deprecated in PHP 7.1)
Remove all reserved (including merely 'not recommended') words as DB table column names
Provide mutex lock on DB logging to prevent recursion under rare failure modes.
Bugfixes:
Remove db_close function on page end - not needed and will not work with persistent DB connections.
Undefined ref_session_write
Some session functions needed to be static to work with CalDAV/CardDAV
CLI interface: argc and argv were reversed
HTML entities double encoded in edited titles
Prevent delivering to empty recipients
Sabre library setting some security headers for SAML after we've emitted HTML content
Always initialise miniApp (caused obscure warning message if not set)
Block 'sys' channels from being 'random profile' candidates
DB update failed email could be sent in the wrong language under rare circumstances
Openid remote authentication used incorrect namespace
URL attached to profile "things" was not linked, always showing the "thing" manage page
New connection wasn't added to default privacy group when "auto-accept" was enabled
Regression: iconfig sharing wasn't working properly
Plugins:
CalDAV/CardDAV plugin provided
Issue sending Diaspora 'like' activities from sources that did not propagate the DCV
Allow 'superblock' to work across API calls from third party clients
statistics.json: use 'zot' as protocol
Issues fixed during testing of ability to follow Diaspora tags
Parse issue with Diaspora reshare content
Chess: moved to main repo, ported to 1.8
Hubzilla 1.6
Cleanup and standardise the interfaces to the "jot" editor
Router re-written to support calling class object methods as controllers

View File

@@ -1,4 +1,4 @@
Copyright (c) 2010-2016 Hubzilla
Copyright (c) 2010-2016 the Hubzilla Community
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@@ -3,8 +3,11 @@
Hubzilla - Community Server
===========================
Connected and linked web communities.
-------------------------------------
Groupware re-imagined and re-invented.
--------------------------------------
Connect and link decentralised web communities.
-----------------------------------------------
<p align="center" markdown="1">
<em><a href="https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt">Installing Hubzilla</a></em>
@@ -44,4 +47,16 @@ Possible website applications include
<em><a href="https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt">Installing Hubzilla</a></em>
</p>
**Who Are We and What Are Our Principles?**
The Hubzilla community is powered by passionate volunteers creating an open source **commons** of decentralised services which are highly integrated and can rival the feature set of centralised providers. We are open to sponsorship and donations to cover expenses and compensate for our time and energy, however the project core is basically non-profit and is not designed for the purpose of commercial gain or exploitation.
Some sites may include monetisation strategies such as subscriptions and *freemium* models where members pay for resources they consume beyond a basic level. The project community supports such monetisation initiatives (nobody should be forced to pay "out of pocket" to provide a service to others), but we maintain the **commons** to provide open and free access of the software to all.
The software is not designed for data collection of its members or providing advertising. We don't have a need or desire for these things and feel that software built around these goals is poorly designed and represents compromised principles and ethics.
As a project, we are inclusive of all beliefs and cultures and do what we are able to provide an environment that is free from hostility and harrassment. Whether or not we succeed in this endaevour requires constant vigilance and help from all members of the community, working together to build an inter-networking tool with amazing potential.
[![Build Status](https://travis-ci.org/redmatrix/hubzilla.svg)](https://travis-ci.org/redmatrix/hubzilla)

View File

@@ -0,0 +1,36 @@
<?php
namespace Zotlabs\Access;
use \Zotlabs\Lib as ZLib;
class PermissionLimits {
static public function Std_Limits() {
$perms = Permissions::Perms();
$limits = array();
foreach($perms as $k => $v) {
if(strstr($k,'view'))
$limits[$k] = PERMS_PUBLIC;
else
$limits[$k] = PERMS_SPECIFIC;
}
return $limits;
}
static public function Set($channel_id,$perm,$perm_limit) {
ZLib\PConfig::Set($channel_id,'perm_limits',$perm,$perm_limit);
}
static public function Get($channel_id,$perm = '') {
if($perm) {
return Zlib\PConfig::Get($channel_id,'perm_limits',$perm);
}
else {
Zlib\PConfig::Load($channel_id);
if(array_key_exists($channel_id,\App::$config) && array_key_exists('perm_limits',\App::$config[$channel_id]))
return \App::$config[$channel_id]['perm_limits'];
return false;
}
}
}

View File

@@ -0,0 +1,215 @@
<?php
namespace Zotlabs\Access;
use Zotlabs\Lib as Zlib;
class PermissionRoles {
static function role_perms($role) {
$ret = array();
$ret['role'] = $role;
switch($role) {
case 'social':
$ret['perms_auto'] = false;
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = true;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'chat', 'post_like', 'republish' ];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'social_restricted':
$ret['perms_auto'] = false;
$ret['default_collection'] = true;
$ret['directory_publish'] = true;
$ret['online'] = true;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'chat', 'post_like' ];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'social_private':
$ret['perms_auto'] = false;
$ret['default_collection'] = true;
$ret['directory_publish'] = false;
$ret['online'] = false;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'post_like' ];
$ret['limits'] = PermissionLimits::Std_Limits();
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
$ret['limits']['view_storage'] = PERMS_SPECIFIC;
break;
case 'forum':
$ret['perms_auto'] = true;
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'post_wall', 'post_comments', 'tag_deliver',
'post_mail', 'post_like' , 'republish', 'chat' ];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'forum_restricted':
$ret['perms_auto'] = false;
$ret['default_collection'] = true;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'post_wall', 'post_comments', 'tag_deliver',
'post_mail', 'post_like' , 'chat' ];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'forum_private':
$ret['perms_auto'] = false;
$ret['default_collection'] = true;
$ret['directory_publish'] = false;
$ret['online'] = false;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'post_wall', 'post_comments',
'post_mail', 'post_like' , 'chat' ];
$ret['limits'] = PermissionLimits::Std_Limits();
$ret['limits']['view_profile'] = PERMS_SPECIFIC;
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
$ret['limits']['view_storage'] = PERMS_SPECIFIC;
$ret['limits']['view_pages'] = PERMS_SPECIFIC;
break;
case 'feed':
$ret['perms_auto'] = true;
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'post_like' , 'republish' ];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'feed_restricted':
$ret['perms_auto'] = false;
$ret['default_collection'] = true;
$ret['directory_publish'] = false;
$ret['online'] = false;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'post_like' , 'republish' ];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'soapbox':
$ret['perms_auto'] = true;
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'post_like' , 'republish' ];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'repository':
$ret['perms_auto'] = true;
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'write_storage', 'write_pages', 'post_wall', 'post_comments', 'tag_deliver',
'post_mail', 'post_like' , 'republish', 'chat' ];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
default:
break;
}
$x = get_config('system','role_perms');
// let system settings over-ride any or all
if($x && is_array($x) && array_key_exists($role,$x))
$ret = array_merge($ret,$x[$role]);
call_hooks('get_role_perms',$ret);
return $ret;
}
static public function roles() {
$roles = [
t('Social Networking') => [
'social' => t('Social - Mostly Public'),
'social_restricted' => t('Social - Restricted'),
'social_private' => t('Social - Private')
],
t('Community Forum') => [
'forum' => t('Forum - Mostly Public'),
'forum_restricted' => t('Forum - Restricted'),
'forum_private' => t('Forum - Private')
],
t('Feed Republish') => [
'feed' => t('Feed - Mostly Public'),
'feed_restricted' => t('Feed - Restricted')
],
t('Special Purpose') => [
'soapbox' => t('Special - Celebrity/Soapbox'),
'repository' => t('Special - Group Repository')
],
t('Other') => [
'custom' => t('Custom/Expert Mode')
]
];
return $roles;
}
}

View File

@@ -0,0 +1,116 @@
<?php
namespace Zotlabs\Access;
use Zotlabs\Lib as Zlib;
class Permissions {
/**
* Extensible permissions.
* To add new permissions, add to the list of $perms below, with a simple description.
* Also visit PermissionRoles.php and add to the $ret['perms_connect'] property for any role
* if this permission should be granted to new connections.
*
* Permissions with 'view' in the name are considered read permissions. Anything
* else requires authentication. Read permission limits are PERMS_PUBLIC and anything else
* is given PERMS_SPECIFIC.
*
* PermissionLimits::Std_limits() retrieves the standard limits. A permission role
* MAY alter an individual setting after retrieving the Std_limits if you require
* something different for a specific permission within the given role.
*
*/
static public function Perms($filter = '') {
$perms = [
'view_stream' => t('Can view my channel stream and posts'),
'send_stream' => t('Can send me their channel stream and posts'),
'view_profile' => t('Can view my default channel profile'),
'view_contacts' => t('Can view my connections'),
'view_storage' => t('Can view my file storage and photos'),
'write_storage' => t('Can upload/modify my file storage and photos'),
'view_pages' => t('Can view my channel webpages'),
'write_pages' => t('Can create/edit my channel webpages'),
'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_like' => t('Can like/dislike profiles and profile things'),
'tag_deliver' => t('Can forward to all my channel connections via @+ mentions in posts'),
'chat' => t('Can chat with me'),
'republish' => t('Can source my public posts in derived channels'),
'delegate' => t('Can administer my channel')
];
$x = array('permissions' => $perms, 'filter' => $filter);
call_hooks('permissions_list',$x);
return($x['permissions']);
}
static public function BlockedAnonPerms() {
// Perms from the above list that are blocked from anonymous observers.
// e.g. you must be authenticated.
$res = array();
$perms = PermissionLimits::Std_limits();
foreach($perms as $perm => $limit) {
if($limit != PERMS_PUBLIC) {
$res[] = $perm;
}
}
$x = array('permissions' => $res);
call_hooks('write_perms',$x);
return($x['permissions']);
}
// converts [ 0 => 'view_stream', ... ]
// to [ 'view_stream' => 1 ]
// for any permissions in $arr;
// Undeclared permissions are set to 0
static public function FilledPerms($arr) {
$everything = self::Perms();
$ret = [];
foreach($everything as $k => $v) {
if(in_array($k,$arr))
$ret[$k] = 1;
else
$ret[$k] = 0;
}
return $ret;
}
static public function FilledAutoperms($channel_id) {
if(! intval(get_pconfig($channel_id,'system','autoperms')))
return false;
$arr = [];
$r = q("select * from pconfig where uid = %d and cat = 'autoperms'",
intval($channel_id)
);
if($r) {
foreach($r as $rr) {
$arr[$rr['k']] = $arr[$rr['v']];
}
}
return $arr;
}
static public function PermsCompare($p1,$p2) {
foreach($p1 as $k => $v) {
if(! array_key_exists($k,$p2))
return false;
if($p1[$k] != $p2[$k])
return false;
}
return true;
}
}

View File

@@ -0,0 +1,55 @@
<?php /** @file */
namespace Zotlabs\Daemon;
require_once('include/zot.php');
require_once('include/hubloc.php');
class Checksites {
static public function run($argc,$argv) {
logger('checksites: start');
if(($argc > 1) && ($argv[1]))
$site_id = $argv[1];
if($site_id)
$sql_options = " and site_url = '" . dbesc($argv[1]) . "' ";
$days = intval(get_config('system','sitecheckdays'));
if($days < 1)
$days = 30;
$r = q("select * from site where site_dead = 0 and site_update < %s - INTERVAL %s and site_type = %d $sql_options ",
db_utcnow(), db_quoteinterval($days . ' DAY'),
intval(SITE_TYPE_ZOT)
);
if(! $r)
return;
foreach($r as $rr) {
if(! strcasecmp($rr['site_url'],z_root()))
continue;
$x = ping_site($rr['site_url']);
if($x['success']) {
logger('checksites: ' . $rr['site_url']);
q("update site set site_update = '%s' where site_url = '%s' ",
dbesc(datetime_convert()),
dbesc($rr['site_url'])
);
}
else {
logger('marking dead site: ' . $x['message']);
q("update site set site_dead = 1 where site_url = '%s' ",
dbesc($rr['site_url'])
);
}
}
return;
}
}

View File

@@ -0,0 +1,14 @@
<?php /** @file */
namespace Zotlabs\Daemon;
require_once('include/socgraph.php');
class Cli_suggest {
static public function run($argc,$argv) {
update_suggestions();
}
}

205
Zotlabs/Daemon/Cron.php Normal file
View File

@@ -0,0 +1,205 @@
<?php /** @file */
namespace Zotlabs\Daemon;
class Cron {
static public function run($argc,$argv) {
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
if(function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload) {
logger('system: load ' . $load . ' too high. Cron deferred to next scheduled run.');
return;
}
}
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
$lockfile = 'store/[data]/cron';
if((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
&& (! get_config('system','override_cron_lockfile'))) {
logger("cron: Already running");
return;
}
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
file_put_contents($lockfile, $x);
logger('cron: start');
// run queue delivery process in the background
Master::Summon(array('Queue'));
Master::Summon(array('Poller'));
// maintenance for mod sharedwithme - check for updated items and remove them
require_once('include/sharedwithme.php');
apply_updates();
// expire any expired mail
q("delete from mail where expires != '%s' and expires < %s ",
dbesc(NULL_DATE),
db_utcnow()
);
// expire any expired items
$r = q("select id from item where expires != '%s' and expires < %s
and item_deleted = 0 ",
dbesc(NULL_DATE),
db_utcnow()
);
if($r) {
require_once('include/items.php');
foreach($r as $rr)
drop_item($rr['id'],false);
}
// delete expired access tokens
$r = q("select atoken_id from atoken where atoken_expires != '%s' && atoken_expires < %s",
dbesc(NULL_DATE),
db_utcnow()
);
if($r) {
require_once('include/security.php');
foreach($r as $rr) {
atoken_delete($rr['atoken_id']);
}
}
// Ensure that every channel pings a directory server once a month. This way we can discover
// channels and sites that quietly vanished and prevent the directory from accumulating stale
// or dead entries.
$r = q("select channel_id from channel where channel_dirdate < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('30 DAY')
);
if($r) {
foreach($r as $rr) {
Master::Summon(array('Directory',$rr['channel_id'],'force'));
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
}
// publish any applicable items that were set to be published in the future
// (time travel posts). Restrict to items that have come of age in the last
// couple of days to limit the query to something reasonable.
$r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
db_utcnow(),
dbesc(datetime_convert('UTC','UTC','now - 2 days'))
);
if($r) {
foreach($r as $rr) {
$x = q("update item set item_delayed = 0 where id = %d",
intval($rr['id'])
);
if($x) {
$z = q("select * from item where id = %d",
intval($message_id)
);
if($z) {
xchan_query($z);
$sync_item = fetch_post_tags($z);
build_sync_packet($sync_item[0]['uid'],
[
'item' => [ encode_item($sync_item[0],true) ]
]
);
}
Master::Summon(array('Notifier','wall-new',$rr['id']));
}
}
}
$abandon_days = intval(get_config('system','account_abandon_days'));
if($abandon_days < 1)
$abandon_days = 0;
// once daily run birthday_updates and then expire in background
// FIXME: add birthday updates, both locally and for xprof for use
// by directory servers
$d1 = intval(get_config('system','last_expire_day'));
$d2 = intval(datetime_convert('UTC','UTC','now','d'));
// Allow somebody to staggger daily activities if they have more than one site on their server,
// or if it happens at an inconvenient (busy) hour.
$h1 = intval(get_config('system','cron_hour'));
$h2 = intval(datetime_convert('UTC','UTC','now','G'));
if(($d2 != $d1) && ($h1 == $h2)) {
Master::Summon(array('Cron_daily'));
}
// update any photos which didn't get imported properly
// This should be rare
$r = q("select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = ''
and xchan_photo_date < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('1 DAY')
);
if($r) {
require_once('include/photo/photo_driver.php');
foreach($r as $rr) {
$photos = import_xchan_photo($rr['xchan_photo_l'],$rr['xchan_hash']);
$x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
where xchan_hash = '%s'",
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
dbesc($photos[3]),
dbesc($rr['xchan_hash'])
);
}
}
// pull in some public posts
if(! get_config('system','disable_discover_tab'))
Master::Summon(array('Externals'));
$generation = 0;
$restart = false;
if(($argc > 1) && ($argv[1] == 'restart')) {
$restart = true;
$generation = intval($argv[2]);
if(! $generation)
killme();
}
reload_plugins();
$d = datetime_convert();
// TODO check to see if there are any cronhooks before wasting a process
if(! $restart)
Master::Summon(array('Cronhooks'));
set_config('system','lastcron',datetime_convert());
//All done - clear the lockfile
@unlink($lockfile);
return;
}
}

View File

@@ -0,0 +1,90 @@
<?php /** @file */
namespace Zotlabs\Daemon;
class Cron_daily {
static public function run($argc,$argv) {
logger('cron_daily: start');
/**
* Cron Daily
*
*/
require_once('include/dir_fns.php');
check_upstream_directory();
// Fire off the Cron_weekly process if it's the correct day.
$d3 = intval(datetime_convert('UTC','UTC','now','N'));
if($d3 == 7) {
Master::Summon(array('Cron_weekly'));
}
// once daily run birthday_updates and then expire in background
// FIXME: add birthday updates, both locally and for xprof for use
// by directory servers
update_birthdays();
// expire any read notifications over a month old
q("delete from notify where seen = 1 and created < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('30 DAY')
);
//update statistics in config
require_once('include/statistics_fns.php');
update_channels_total_stat();
update_channels_active_halfyear_stat();
update_channels_active_monthly_stat();
update_local_posts_stat();
// expire old delivery reports
$keep_reports = intval(get_config('system','expire_delivery_reports'));
if($keep_reports === 0)
$keep_reports = 10;
q("delete from dreport where dreport_time < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval($keep_reports . ' DAY')
);
// expire any expired accounts
downgrade_accounts();
// If this is a directory server, request a sync with an upstream
// directory at least once a day, up to once every poll interval.
// Pull remote changes and push local changes.
// potential issue: how do we keep from creating an endless update loop?
$dirmode = get_config('system','directory_mode');
if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
require_once('include/dir_fns.php');
sync_directories($dirmode);
}
Master::Summon(array('Expire'));
Master::Summon(array('Cli_suggest'));
require_once('include/hubloc.php');
remove_obsolete_hublocs();
call_hooks('cron_daily',datetime_convert());
set_config('system','last_expire_day',$d2);
/**
* End Cron Daily
*/
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Zotlabs\Daemon;
class Cron_weekly {
static public function run($argc,$argv) {
/**
* Cron Weekly
*
* Actions in the following block are executed once per day only on Sunday (once per week).
*
*/
call_hooks('cron_weekly',datetime_convert());
z_check_cert();
require_once('include/hubloc.php');
prune_hub_reinstalls();
mark_orphan_hubsxchans();
// get rid of really old poco records
q("delete from xlink where xlink_updated < %s - INTERVAL %s and xlink_static = 0 ",
db_utcnow(), db_quoteinterval('14 DAY')
);
$dirmode = intval(get_config('system','directory_mode'));
if($dirmode === DIRECTORY_MODE_SECONDARY || $dirmode === DIRECTORY_MODE_PRIMARY) {
logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . urlencode(z_root()) . '&realm=' . urlencode(get_directory_realm())),true));
}
// Check for dead sites
Master::Summon(array('Checksites'));
// update searchable doc indexes
Master::Summon(array('Importdoc'));
/**
* End Cron Weekly
*/
}
}

View File

@@ -0,0 +1,17 @@
<?php /** @file */
namespace Zotlabs\Daemon;
class Cronhooks {
static public function run($argc,$argv){
logger('cronhooks: start');
$d = datetime_convert();
call_hooks('cron', $d);
return;
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace Zotlabs\Daemon;
// generate a curl compatible cookie file with an authenticated session for the given channel_id.
// If this file is then used with curl and the destination url is sent through zid() or manually
// manipulated to add a zid, it should allow curl to provide zot magic-auth across domains.
// Handles expiration of stale cookies currently by deleting them and rewriting the file.
class CurlAuth {
static public function run($argc,$argv) {
if($argc != 2)
killme();
\App::$session->start();
$_SESSION['authenticated'] = 1;
$_SESSION['uid'] = $argv[1];
$x = session_id();
$f = 'store/[data]/cookie_' . $argv[1];
$c = 'store/[data]/cookien_' . $argv[1];
$e = file_exists($f);
$output = '';
if($e) {
$lines = file($f);
if($lines) {
foreach($lines as $line) {
if(strlen($line) > 0 && $line[0] != '#' && substr_count($line, "\t") == 6) {
$tokens = explode("\t", $line);
$tokens = array_map('trim', $tokens);
if($tokens[4] > time()) {
$output .= $line . "\n";
}
}
else
$output .= $line;
}
}
}
$t = time() + (24 * 3600);
file_put_contents($f, $output . 'HttpOnly_' . \App::get_hostname() . "\tFALSE\t/\tTRUE\t$t\tPHPSESSID\t" . $x, (($e) ? FILE_APPEND : 0));
file_put_contents($c,$x);
killme();
}
}

View File

@@ -0,0 +1,85 @@
<?php /** @file */
namespace Zotlabs\Daemon;
require_once('include/zot.php');
require_once('include/queue_fn.php');
class Deliver {
static public function run($argc,$argv) {
if($argc < 2)
return;
logger('deliver: invoked: ' . print_r($argv,true), LOGGER_DATA);
for($x = 1; $x < $argc; $x ++) {
if(! $argv[$x])
continue;
$dresult = null;
$r = q("select * from outq where outq_hash = '%s' limit 1",
dbesc($argv[$x])
);
if($r) {
$notify = json_decode($r[0]['outq_notify'],true);
// Messages without an outq_msg will need to go via the web, even if it's a
// local delivery. This includes conversation requests and refresh packets.
if(($r[0]['outq_posturl'] === z_root() . '/post') && ($r[0]['outq_msg'])) {
logger('deliver: local delivery', LOGGER_DEBUG);
// local delivery
// we should probably batch these and save a few delivery processes
if($r[0]['outq_msg']) {
$m = json_decode($r[0]['outq_msg'],true);
if(array_key_exists('message_list',$m)) {
foreach($m['message_list'] as $mm) {
$msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $mm)))));
zot_import($msg,z_root());
}
}
else {
$msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $m)))));
$dresult = zot_import($msg,z_root());
}
remove_queue_item($r[0]['outq_hash']);
if($dresult && is_array($dresult)) {
foreach($dresult as $xx) {
if(is_array($xx) && array_key_exists('message_id',$xx)) {
if(delivery_report_is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
dbesc($xx['message_id']),
dbesc($xx['location']),
dbesc($xx['recipient']),
dbesc($xx['status']),
dbesc(datetime_convert($xx['date'])),
dbesc($xx['sender'])
);
}
}
}
}
q("delete from dreport where dreport_queue = '%s'",
dbesc($argv[$x])
);
}
}
// otherwise it's a remote delivery - call queue_deliver() with the $immediate flag
queue_deliver($r[0],true);
}
}
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Zotlabs\Daemon;
require_once('include/zot.php');
class Deliver_hooks {
static public function run($argc,$argv) {
if($argc < 2)
return;
$r = q("select * from item where id = '%d'",
intval($argv[1])
);
if($r)
call_hooks('notifier_normal',$r[0]);
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace Zotlabs\Daemon;
require_once('include/zot.php');
require_once('include/dir_fns.php');
require_once('include/queue_fn.php');
class Directory {
static public function run($argc,$argv){
if($argc < 2)
return;
$force = false;
$pushall = true;
if($argc > 2) {
if($argv[2] === 'force')
$force = true;
if($argv[2] === 'nopush')
$pushall = false;
}
logger('directory update', LOGGER_DEBUG);
$dirmode = get_config('system','directory_mode');
if($dirmode === false)
$dirmode = DIRECTORY_MODE_NORMAL;
$x = q("select * from channel where channel_id = %d limit 1",
intval($argv[1])
);
if(! $x)
return;
$channel = $x[0];
if($dirmode != DIRECTORY_MODE_NORMAL) {
// this is an in-memory update and we don't need to send a network packet.
local_dir_update($argv[1],$force);
q("update channel set channel_dirdate = '%s' where channel_id = %d",
dbesc(datetime_convert()),
intval($channel['channel_id'])
);
// Now update all the connections
if($pushall)
Master::Summon(array('Notifier','refresh_all',$channel['channel_id']));
return;
}
// otherwise send the changes upstream
$directory = find_upstream_directory($dirmode);
$url = $directory['url'] . '/post';
// ensure the upstream directory is updated
$packet = zot_build_packet($channel,(($force) ? 'force_refresh' : 'refresh'));
$z = zot_zot($url,$packet);
// re-queue if unsuccessful
if(! $z['success']) {
/** @FIXME we aren't updating channel_dirdate if we have to queue
* the directory packet. That means we'll try again on the next poll run.
*/
$hash = random_string();
queue_insert(array(
'hash' => $hash,
'account_id' => $channel['channel_account_id'],
'channel_id' => $channel['channel_id'],
'posturl' => $url,
'notify' => $packet,
));
}
else {
q("update channel set channel_dirdate = '%s' where channel_id = %d",
dbesc(datetime_convert()),
intval($channel['channel_id'])
);
}
// Now update all the connections
if($pushall)
Master::Summon(array('Notifier','refresh_all',$channel['channel_id']));
}
}

93
Zotlabs/Daemon/Expire.php Normal file
View File

@@ -0,0 +1,93 @@
<?php
namespace Zotlabs\Daemon;
class Expire {
static public function run($argc,$argv){
cli_startup();
// perform final cleanup on previously delete items
$r = q("select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('10 DAY')
);
if ($r) {
foreach ($r as $rr) {
drop_item($rr['id'], false, DROPITEM_PHASE2);
}
}
// physically remove anything that has been deleted for more than two months
/** @FIXME - this is a wretchedly inefficient query */
$r = q("delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('36 DAY')
);
/** @FIXME make this optional as it could have a performance impact on large sites */
if (intval(get_config('system', 'optimize_items')))
q("optimize table item");
logger('expire: start', LOGGER_DEBUG);
$site_expire = get_config('system', 'default_expire_days');
logger('site_expire: ' . $site_expire);
$r = q("SELECT channel_id, channel_system, channel_address, channel_expire_days from channel where true");
if ($r) {
foreach ($r as $rr) {
// expire the sys channel separately
if (intval($rr['channel_system']))
continue;
// service class default (if non-zero) over-rides the site default
$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
if (intval($service_class_expire))
$channel_expire = $service_class_expire;
else
$channel_expire = $site_expire;
if (intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) ||
intval($rr['channel_expire_days'] == 0)) {
$expire_days = $channel_expire;
} else {
$expire_days = $rr['channel_expire_days'];
}
// if the site or service class expiration is non-zero and less than person expiration, use that
logger('Expire: ' . $rr['channel_address'] . ' interval: ' . $expire_days, LOGGER_DEBUG);
item_expire($rr['channel_id'], $expire_days);
}
}
$x = get_sys_channel();
if ($x) {
// this should probably just fetch the channel_expire_days from the sys channel,
// but there's no convenient way to set it.
$expire_days = get_config('system', 'sys_expire_days');
if ($expire_days === false)
$expire_days = 30;
if (intval($site_expire) && (intval($site_expire) < intval($expire_days))) {
$expire_days = $site_expire;
}
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
if ($expire_days)
item_expire($x['channel_id'], $expire_days);
logger('Expire: sys: done', LOGGER_DEBUG);
}
}
}

View File

@@ -0,0 +1,98 @@
<?php /** @file */
namespace Zotlabs\Daemon;
require_once('include/zot.php');
require_once('include/channel.php');
class Externals {
static public function run($argc,$argv){
$total = 0;
$attempts = 0;
logger('externals: startup', LOGGER_DEBUG);
// pull in some public posts
while($total == 0 && $attempts < 3) {
$arr = array('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'] = '';
$results = process_delivery(array('hash' => 'undefined'), get_item_elements($message),
array(array('hash' => $sys['xchan_hash'])), false, true);
$total ++;
}
logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
}
}
}
}
}
}

33
Zotlabs/Daemon/Gprobe.php Normal file
View File

@@ -0,0 +1,33 @@
<?php /** @file */
namespace Zotlabs\Daemon;
require_once('include/zot.php');
// performs zot_finger on $argv[1], which is a hex_encoded webbie/reddress
class Gprobe {
static public function run($argc,$argv) {
if($argc != 2)
return;
$url = hex2bin($argv[1]);
if(! strpos($url,'@'))
return;
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
dbesc($url)
);
if(! $r) {
$j = \Zotlabs\Zot\Finger::run($url,null);
if($j['success']) {
$y = import_xchan($j);
}
}
return;
}
}

35
Zotlabs/Daemon/Importdoc.php Executable file
View File

@@ -0,0 +1,35 @@
<?php
namespace Zotlabs\Daemon;
class Importdoc {
static public function run($argc,$argv) {
require_once('include/help.php');
self::update_docs_dir('doc/*');
}
static public function update_docs_dir($s) {
$f = basename($s);
$d = dirname($s);
if($s === 'doc/html')
return;
$files = glob("$d/$f");
if($files) {
foreach($files as $fi) {
if($fi === 'doc/html')
continue;
if(is_dir($fi))
self::update_docs_dir("$fi/*");
else
store_doc_file($fi);
}
}
}
}

31
Zotlabs/Daemon/Master.php Normal file
View File

@@ -0,0 +1,31 @@
<?php
namespace Zotlabs\Daemon;
if(array_search( __file__ , get_included_files()) === 0) {
require_once('include/cli_startup.php');
array_shift($argv);
$argc = count($argv);
if($argc)
Master::Release($argc,$argv);
killme();
}
class Master {
static public function Summon($arr) {
proc_run('php','Zotlabs/Daemon/Master.php',$arr);
}
static public function Release($argc,$argv) {
cli_startup();
logger('Master: release: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
require_once('Zotlabs/Daemon/' . $argv[0] . '.php');
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc,$argv);
}
}

663
Zotlabs/Daemon/Notifier.php Normal file
View File

@@ -0,0 +1,663 @@
<?php /** @file */
namespace Zotlabs\Daemon;
require_once('include/queue_fn.php');
require_once('include/html2plain.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.
*
* The basic flow is:
* Identify the type of message
* Collect any information that needs to be sent
* Convert it into a suitable generic format for sending
* Figure out who the recipients are and if we need to relay
* through a conversation owner
* Once we know what recipients are involved, collect a list of
* destination sites
* Build and store a queue item for each unique site and invoke
* a delivery process for each site or a small number of sites (1-3)
* and add a slight delay between each delivery invocation if desired (usually)
*
*/
/*
* The notifier is typically called with:
*
* Zotlabs\Daemon\Master::Summon(array('Notifier', COMMAND, ITEM_ID));
*
* where COMMAND is one of the following:
*
* activity (in diaspora.php, dfrn_confirm.php, profiles.php)
* comment-import (in diaspora.php, items.php)
* comment-new (in item.php)
* drop (in diaspora.php, items.php, photos.php)
* edit_post (in item.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)
*
* and ITEM_ID is the id of the item in the database that needs to be sent to others.
*
* ZOT
* permission_create abook_id
* permission_update abook_id
* refresh_all channel_id
* purge_all channel_id
* 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
*
*/
require_once('include/zot.php');
require_once('include/queue_fn.php');
require_once('include/datetime.php');
require_once('include/items.php');
require_once('include/bbcode.php');
require_once('include/channel.php');
class Notifier {
static public function run($argc,$argv){
if($argc < 3)
return;
logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
$cmd = $argv[1];
$item_id = $argv[2];
$extra = (($argc > 3) ? $argv[3] : null);
if(! $item_id)
return;
$sys = get_sys_channel();
$deliveries = array();
$dead_hubs = array();
$dh = q("select site_url from site where site_dead = 1");
if($dh) {
foreach($dh as $dead) {
$dead_hubs[] = $dead['site_url'];
}
}
$request = false;
$mail = false;
$top_level = false;
$location = false;
$recipients = array();
$url_recipients = array();
$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($item['channel_id'])
);
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];
$private = true;
$recipients[] = $xchan;
$packet_type = 'request';
$normal_mode = false;
}
elseif($cmd == 'permission_update' || $cmd == '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 = array('sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => '');
if($cmd == 'permission_create')
call_hooks('permissions_create',$perm_update);
else
call_hooks('permissions_update',$perm_update);
if($perm_update['success']) {
if($perm_update['deliveries']) {
$deliveries[] = $perm_update['deliveries'];
do_delivery($deliveries);
}
return;
}
else {
$recipients[] = $r[0]['abook_xchan'];
$private = false;
$packet_type = 'refresh';
$packet_recips = array(array('guid' => $r[0]['xchan_guid'],'guid_sig' => $r[0]['xchan_guid_sig'],'hash' => $r[0]['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($item_id)
);
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",
intval($item_id)
);
if($s)
$channel = $s[0];
$uid = $item_id;
$recipients = array();
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($item_id)
);
if($r) {
foreach($r as $rr) {
$recipients[] = $rr['abook_xchan'];
}
}
$encoded_item = array('locations' => zot_encode_locations($channel),'type' => 'location', 'encoding' => 'zot');
$target_item = array('aid' => $channel['channel_account_id'],'uid' => $channel['channel_id']);
$private = false;
$packet_type = 'location';
$location = true;
}
elseif($cmd === 'purge_all') {
logger('notifier: purge_all: ' . $item_id);
$s = q("select * from channel where channel_id = %d limit 1",
intval($item_id)
);
if($s)
$channel = $s[0];
$uid = $item_id;
$recipients = array();
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($item_id)
);
if($r) {
foreach($r as $rr) {
$recipients[] = $rr['abook_xchan'];
}
}
$private = false;
$packet_type = 'purge';
}
else {
// Normal items
// Fetch the target item
$r = q("SELECT * FROM item WHERE id = %d and parent != 0 LIMIT 1",
intval($item_id)
);
if(! $r)
return;
xchan_query($r);
$r = fetch_post_tags($r);
$target_item = $r[0];
$deleted_item = false;
if(intval($target_item['item_deleted'])) {
logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
$deleted_item = true;
}
if(intval($target_item['item_type']) != ITEM_TYPE_POST) {
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
return;
}
// Check for non published items, but allow an exclusion for transmitting hidden file activities
if(intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
( intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) {
logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
return;
}
if(strpos($target_item['postopts'],'nodeliver') !== false) {
logger('notifier: target item is undeliverable', LOGGER_DEBUG);
return;
}
$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($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);
return;
}
if($target_item['id'] == $target_item['parent']) {
$parent_item = $target_item;
$top_level_post = true;
}
else {
// fetch the parent item
$r = q("SELECT * from item where id = %d order by id asc",
intval($target_item['parent'])
);
if(! $r)
return;
if(strpos($r[0]['postopts'],'nodeliver') !== false) {
logger('notifier: target item is undeliverable', LOGGER_DEBUG, LOG_NOTICE);
return;
}
xchan_query($r);
$r = fetch_post_tags($r);
$parent_item = $r[0];
$top_level_post = false;
}
// avoid looping of discover items 12/4/2014
if($sys && $parent_item['uid'] == $sys['channel_id'])
return;
$encoded_item = encode_item($target_item);
// Send comments to the owner to re-deliver to everybody in the conversation
// We only do this if the item in question originated on this site. This prevents looping.
// To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
// Relaying should never be initiated on a post that arrived from elsewhere.
// We should normally be able to rely on ITEM_ORIGIN, but start_delivery_chain() incorrectly set this
// 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;
// $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
logger('notifier: relay_to_owner: ' . (($relay_to_owner) ? 'true' : 'false'), LOGGER_DATA, LOG_DEBUG);
logger('notifier: top_level_post: ' . (($top_level_post) ? 'true' : 'false'), LOGGER_DATA, LOG_DEBUG);
// tag_deliver'd post which needs to be sent back to the original author
if(($cmd === 'uplink') && intval($parent_item['item_uplink']) && (! $top_level_post)) {
logger('notifier: uplink');
$uplink = true;
}
if(($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
logger('notifier: followup relay', LOGGER_DEBUG);
$recipients = array(($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
$private = true;
if(! $encoded_item['flags'])
$encoded_item['flags'] = array();
$encoded_item['flags'][] = 'relay';
}
else {
logger('notifier: normal distribution', LOGGER_DEBUG);
if($cmd === 'relay')
logger('notifier: owner relay');
// 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')) {
// don't uplink a relayed post to the relay owner
if($parent_item['source_xchan'] !== $parent_item['owner_xchan']) {
logger('notifier: uplinking this item');
Master::Summon(array('Notifier','uplink',$item_id));
}
}
$private = false;
$recipients = collect_recipients($parent_item,$private);
// FIXME add any additional recipients such as mentions, etc.
// don't send deletions onward for other people's stuff
// TODO verify this is needed - copied logic from same place in old code
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);
stringify_array_elms($recipients);
if(! $recipients)
return;
// logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG);
$env_recips = (($private) ? array() : null);
$details = q("select xchan_hash, xchan_instance_url, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . implode(',',$recipients) . ")");
$recip_list = array();
if($details) {
foreach($details as $d) {
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
if($private)
$env_recips[] = array('guid' => $d['xchan_guid'],'guid_sig' => $d['xchan_guid_sig'],'hash' => $d['xchan_hash']);
if($d['xchan_network'] === 'mail' && $normal_mode) {
$delivery_options = get_xconfig($d['xchan_hash'],'system','delivery_mode');
if(! $delivery_options)
format_and_send_email($channel,$d,$target_item);
}
}
}
$narr = array(
'channel' => $channel,
'env_recips' => $env_recips,
'packet_recips' => $packet_recips,
'recipients' => $recipients,
'item' => $item,
'target_item' => $target_item,
'top_level_post' => $top_level_post,
'private' => $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,
'normal_mode' => $normal_mode,
'packet_type' => $packet_type,
'walltowall' => $walltowall,
'queued' => array()
);
call_hooks('notifier_process', $narr);
if($narr['queued']) {
foreach($narr['queued'] as $pq)
$deliveries[] = $pq;
}
// notifier_process can alter the recipient list
$recipients = $narr['recipients'];
$env_recips = $narr['env_recips'];
$packet_recips = $narr['packet_recips'];
if(($private) && (! $env_recips)) {
// shouldn't happen
logger('notifier: private message with no envelope recipients.' . print_r($argv,true), LOGGER_NORMAL, LOG_NOTICE);
}
logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list,true), LOGGER_DEBUG);
// Now we have collected recipients (except for external mentions, FIXME)
// Let's reduce this to a set of hubs.
$r = q("select * from hubloc where hubloc_hash in (" . implode(',',$recipients) . ")
and hubloc_error = 0 and hubloc_deleted = 0"
);
if(! $r) {
logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
return;
}
$hubs = $r;
/**
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey, since it may have been
* a re-install which has not yet been detected and pruned.
* For other networks which don't have or require sitekeys, we'll have to use the URL
*/
$hublist = array(); // this provides an easily printable list for the logs
$dhubs = array(); // delivery hubs where we store our resulting unique array
$keys = array(); // array of keys to check uniquness for zot hubs
$urls = array(); // array of urls to check uniqueness of hubs from other networks
foreach($hubs as $hub) {
if(in_array($hub['hubloc_url'],$dead_hubs)) {
logger('skipping dead hub: ' . $hub['hubloc_url'], LOGGER_DEBUG, LOG_INFO);
continue;
}
if($hub['hubloc_network'] == 'zot') {
if(! in_array($hub['hubloc_sitekey'],$keys)) {
$hublist[] = $hub['hubloc_host'];
$dhubs[] = $hub;
$keys[] = $hub['hubloc_sitekey'];
}
}
else {
if(! in_array($hub['hubloc_url'],$urls)) {
$hublist[] = $hub['hubloc_host'];
$dhubs[] = $hub;
$urls[] = $hub['hubloc_url'];
}
}
}
logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG, LOG_DEBUG);
foreach($dhubs as $hub) {
if($hub['hubloc_network'] !== 'zot') {
$narr = array(
'channel' => $channel,
'env_recips' => $env_recips,
'packet_recips' => $packet_recips,
'recipients' => $recipients,
'item' => $item,
'target_item' => $target_item,
'hub' => $hub,
'top_level_post' => $top_level_post,
'private' => $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,
'normal_mode' => $normal_mode,
'packet_type' => $packet_type,
'walltowall' => $walltowall,
'queued' => array()
);
call_hooks('notifier_hub',$narr);
if($narr['queued']) {
foreach($narr['queued'] as $pq)
$deliveries[] = $pq;
}
continue;
}
// singleton deliveries by definition 'not got zot'.
// Single deliveries are other federated networks (plugins) and we're essentially
// delivering only to those that have this site url in their abook_instance
// and only from within a sync operation. This means if you post from a clone,
// and a connection is connected to one of your other clones; assuming that hub
// is running it will receive a sync packet. On receipt of this sync packet it
// will invoke a delivery to those connections which are connected to just that
// hub instance.
if($cmd === 'single_mail' || $cmd === 'single_activity') {
continue;
}
// default: zot protocol
$hash = random_string();
$packet = null;
if($packet_type === 'refresh' || $packet_type === 'purge') {
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
}
elseif($packet_type === 'request') {
$packet = zot_build_packet($channel,$packet_type,$env_recips,$hub['hubloc_sitekey'],$hash,
array('message_id' => $request_message_id)
);
}
if($packet) {
queue_insert(array(
'hash' => $hash,
'account_id' => $channel['channel_account_id'],
'channel_id' => $channel['channel_id'],
'posturl' => $hub['hubloc_callback'],
'notify' => $packet
));
}
else {
$packet = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash);
queue_insert(array(
'hash' => $hash,
'account_id' => $target_item['aid'],
'channel_id' => $target_item['uid'],
'posturl' => $hub['hubloc_callback'],
'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) {
$x = q("select * from hook where hook = 'notifier_normal'");
if($x)
Master::Summon(array('Deliver_hooks',$target_item['id']));
}
if($deliveries)
do_delivery($deliveries);
logger('notifier: basic loop complete.', LOGGER_DEBUG);
call_hooks('notifier_end',$target_item);
logger('notifer: complete.');
return;
}
}

View File

@@ -0,0 +1,76 @@
<?php /** @file */
namespace Zotlabs\Daemon;
require_once('include/zot.php');
require_once('include/dir_fns.php');
class Onedirsync {
static public function run($argc,$argv) {
logger('onedirsync: start ' . intval($argv[1]));
if(($argc > 1) && (intval($argv[1])))
$update_id = intval($argv[1]);
if(! $update_id) {
logger('onedirsync: no update');
return;
}
$r = q("select * from updates where ud_id = %d limit 1",
intval($update_id)
);
if(! $r)
return;
if(($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (! $r[0]['ud_addr']))
return;
// Have we probed this channel more recently than the other directory server
// (where we received this update from) ?
// If we have, we don't need to do anything except mark any older entries updated
$x = q("select * from updates where ud_addr = '%s' and ud_date > '%s' and ( ud_flags & %d )>0 order by ud_date desc limit 1",
dbesc($r[0]['ud_addr']),
dbesc($r[0]['ud_date']),
intval(UPDATE_FLAGS_UPDATED)
);
if($x) {
$y = q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
intval(UPDATE_FLAGS_UPDATED),
dbesc($r[0]['ud_addr']),
intval(UPDATE_FLAGS_UPDATED),
dbesc($x[0]['ud_date'])
);
return;
}
// ignore doing an update if this ud_addr refers to a known dead hubloc
$h = q("select * from hubloc where hubloc_addr = '%s' limit 1",
dbesc($r[0]['ud_addr'])
);
if(($h) && ($h[0]['hubloc_status'] & HUBLOC_OFFLINE)) {
$y = q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
intval(UPDATE_FLAGS_UPDATED),
dbesc($r[0]['ud_addr']),
intval(UPDATE_FLAGS_UPDATED)
);
return;
}
// 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 && $h[0]['hubloc_network'] !== 'zot')
return;
update_directory_entry($r[0]);
return;
}
}

154
Zotlabs/Daemon/Onepoll.php Normal file
View File

@@ -0,0 +1,154 @@
<?php /** @file */
namespace Zotlabs\Daemon;
require_once('include/zot.php');
require_once('include/socgraph.php');
class Onepoll {
static public function run($argc,$argv) {
logger('onepoll: start');
if(($argc > 1) && (intval($argv[1])))
$contact_id = intval($argv[1]);
if(! $contact_id) {
logger('onepoll: no contact');
return;
}
$d = datetime_convert();
$contacts = q("SELECT abook.*, xchan.*, account.*
FROM abook LEFT JOIN account on abook_account = account_id left join xchan on xchan_hash = abook_xchan
where abook_id = %d
and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
AND (( account_flags = %d ) OR ( account_flags = %d )) limit 1",
intval($contact_id),
intval(ACCOUNT_OK),
intval(ACCOUNT_UNVERIFIED)
);
if(! $contacts) {
logger('onepoll: abook_id not found: ' . $contact_id);
return;
}
$contact = $contacts[0];
$t = $contact['abook_updated'];
$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)
);
if(! $r)
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))
? datetime_convert('UTC','UTC','now - 7 days')
: datetime_convert('UTC','UTC',$contact['abook_updated'] . ' - 2 days')
);
if($contact['xchan_network'] === 'rss') {
logger('onepoll: processing feed ' . $contact['xchan_name'], LOGGER_DEBUG);
handle_feed($importer['channel_id'],$contact_id,$contact['xchan_hash']);
q("update abook set abook_connected = '%s' where abook_id = %d",
dbesc(datetime_convert()),
intval($contact['abook_id'])
);
return;
}
if($contact['xchan_network'] !== 'zot')
return;
// update permissions
$x = zot_refresh($contact,$importer);
$responded = false;
$updated = datetime_convert();
$connected = datetime_convert();
if(! $x) {
// mark for death by not updating abook_connected, this is caught in include/poller.php
q("update abook set abook_updated = '%s' where abook_id = %d",
dbesc($updated),
intval($contact['abook_id'])
);
}
else {
q("update abook set abook_updated = '%s', abook_connected = '%s' where abook_id = %d",
dbesc($updated),
dbesc($connected),
intval($contact['abook_id'])
);
$responded = true;
}
if(! $responded)
return;
if($contact['xchan_connurl']) {
$fetch_feed = true;
$x = null;
$can_view_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'their_perms','view_stream'));
if(! $can_view_stream)
$fetch_feed = false;
if($fetch_feed) {
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
$feedurl .= '?f=&mindate=' . urlencode($last_update);
$x = z_fetch_url($feedurl);
logger('feed_update: ' . print_r($x,true), LOGGER_DATA);
}
if(($x) && ($x['success'])) {
$total = 0;
logger('onepoll: feed update ' . $contact['xchan_name'] . ' ' . $feedurl);
$j = json_decode($x['body'],true);
if($j['success'] && $j['messages']) {
foreach($j['messages'] as $message) {
$results = process_delivery(array('hash' => $contact['xchan_hash']), get_item_elements($message),
array(array('hash' => $importer['xchan_hash'])), false);
logger('onepoll: feed_update: process_delivery: ' . print_r($results,true), LOGGER_DATA);
$total ++;
}
logger("onepoll: $total messages processed");
}
}
}
// update the poco details for this connection
if($contact['xchan_connurl']) {
$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')
);
if(! $r) {
poco_load($contact['xchan_hash'],$contact['xchan_connurl']);
}
}
return;
}
}

202
Zotlabs/Daemon/Poller.php Normal file
View File

@@ -0,0 +1,202 @@
<?php /** @file */
namespace Zotlabs\Daemon;
class Poller {
static public function run($argc,$argv) {
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
if(function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload) {
logger('system: load ' . $load . ' too high. Poller deferred to next scheduled run.');
return;
}
}
$interval = intval(get_config('system','poll_interval'));
if(! $interval)
$interval = ((get_config('system','delivery_interval') === false) ? 3 : intval(get_config('system','delivery_interval')));
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
$lockfile = 'store/[data]/poller';
if((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
&& (! get_config('system','override_poll_lockfile'))) {
logger("poller: Already running");
return;
}
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
file_put_contents($lockfile, $x);
logger('poller: start');
$manual_id = 0;
$generation = 0;
$force = false;
$restart = false;
if(($argc > 1) && ($argv[1] == 'force'))
$force = true;
if(($argc > 1) && ($argv[1] == 'restart')) {
$restart = true;
$generation = intval($argv[2]);
if(! $generation)
killme();
}
if(($argc > 1) && intval($argv[1])) {
$manual_id = intval($argv[1]);
$force = true;
}
$sql_extra = (($manual_id) ? " AND abook_id = " . intval($manual_id) . " " : "");
reload_plugins();
$d = datetime_convert();
// Only poll from those with suitable relationships
$abandon_sql = (($abandon_days)
? sprintf(" AND account_lastlog > %s - INTERVAL %s ", db_utcnow(), db_quoteinterval(intval($abandon_days).' DAY'))
: ''
);
$randfunc = db_getfunc('RAND');
$contacts = q("SELECT * FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
LEFT JOIN account on abook_account = account_id
where abook_self = 0
$sql_extra
AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
intval(ACCOUNT_OK),
intval(ACCOUNT_UNVERIFIED) // FIXME
);
if($contacts) {
foreach($contacts as $contact) {
$update = false;
$t = $contact['abook_updated'];
$c = $contact['abook_connected'];
if(intval($contact['abook_feed'])) {
$min = service_class_fetch($contact['abook_channel'],'minimum_feedcheck_minutes');
if(! $min)
$min = intval(get_config('system','minimum_feedcheck_minutes'));
if(! $min)
$min = 60;
$x = datetime_convert('UTC','UTC',"now - $min minutes");
if($c < $x) {
Master::Summon(array('Onepoll',$contact['abook_id']));
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
continue;
}
if($contact['xchan_network'] !== 'zot')
continue;
if($c == $t) {
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day"))
$update = true;
}
else {
// if we've never connected with them, start the mark for death countdown from now
if($c == NULL_DATE) {
$r = q("update abook set abook_connected = '%s' where abook_id = %d",
dbesc(datetime_convert()),
intval($contact['abook_id'])
);
$c = datetime_convert();
$update = true;
}
// He's dead, Jim
if(strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $c . " + 30 day")) > 0) {
$r = q("update abook set abook_archived = 1 where abook_id = %d",
intval($contact['abook_id'])
);
$update = false;
continue;
}
if(intval($contact['abook_archived'])) {
$update = false;
continue;
}
// might be dead, so maybe don't poll quite so often
// recently deceased, so keep up the regular schedule for 3 days
if((strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $c . " + 3 day")) > 0)
&& (strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $t . " + 1 day")) > 0))
$update = true;
// After that back off and put them on a morphine drip
if(strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $t . " + 2 day")) > 0) {
$update = true;
}
}
if(intval($contact['abook_pending']) || intval($contact['abook_archived']) || intval($contact['abook_ignored']) || intval($contact['abook_blocked']))
continue;
if((! $update) && (! $force))
continue;
Master::Summon(array('Onepoll',$contact['abook_id']));
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
}
if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
$r = q("SELECT u.ud_addr, u.ud_id, u.ud_last FROM updates AS u INNER JOIN (SELECT ud_addr, max(ud_id) AS ud_id FROM updates WHERE ( ud_flags & %d ) = 0 AND ud_addr != '' AND ( ud_last = '%s' OR ud_last > %s - INTERVAL %s ) GROUP BY ud_addr) AS s ON s.ud_id = u.ud_id ",
intval(UPDATE_FLAGS_UPDATED),
dbesc(NULL_DATE),
db_utcnow(), db_quoteinterval('7 DAY')
);
if($r) {
foreach($r as $rr) {
// If they didn't respond when we attempted before, back off to once a day
// After 7 days we won't bother anymore
if($rr['ud_last'] != NULL_DATE)
if($rr['ud_last'] > datetime_convert('UTC','UTC', 'now - 1 day'))
continue;
Master::Summon(array('Onedirsync',$rr['ud_id']));
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
}
}
set_config('system','lastpoll',datetime_convert());
//All done - clear the lockfile
@unlink($lockfile);
return;
}
}

90
Zotlabs/Daemon/Queue.php Normal file
View File

@@ -0,0 +1,90 @@
<?php /** @file */
namespace Zotlabs\Daemon;
require_once('include/queue_fn.php');
require_once('include/zot.php');
class Queue {
static public function run($argc,$argv) {
require_once('include/items.php');
require_once('include/bbcode.php');
if(argc() > 1)
$queue_id = argv(1);
else
$queue_id = 0;
logger('queue: start');
// delete all queue items more than 3 days old
// but first mark these sites dead if we haven't heard from them in a month
$r = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('3 DAY')
);
if($r) {
foreach($r as $rr) {
$site_url = '';
$h = parse_url($rr['outq_posturl']);
$desturl = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
q("update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - INTERVAL %s",
dbesc($desturl),
db_utcnow(), db_quoteinterval('1 MONTH')
);
}
}
$r = q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('3 DAY')
);
if($queue_id) {
$r = q("SELECT * FROM outq WHERE outq_hash = '%s' LIMIT 1",
dbesc($queue_id)
);
}
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
// 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
// "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.
// FIXME: can we sort postgres on outq_priority and maintain the 'distinct' ?
// The order by max(outq_priority) might be a dodgy query because of the group by.
// The desired result is to return a sequence in the order most likely to be delivered in this run.
// If a hub has already been sitting in the queue for a few days, they should be delivered last;
// hence every failure should drop them further down the priority list.
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$prefix = 'DISTINCT ON (outq_posturl)';
$suffix = 'ORDER BY outq_posturl';
} else {
$prefix = '';
$suffix = 'GROUP BY outq_posturl ORDER BY max(outq_priority)';
}
$r = q("SELECT $prefix * FROM outq WHERE outq_delivered = 0 and (( outq_created > %s - INTERVAL %s and outq_updated < %s - INTERVAL %s ) OR ( outq_updated < %s - INTERVAL %s )) $suffix",
db_utcnow(), db_quoteinterval('12 HOUR'),
db_utcnow(), db_quoteinterval('15 MINUTE'),
db_utcnow(), db_quoteinterval('1 HOUR')
);
}
if(! $r)
return;
foreach($r as $rr) {
queue_deliver($rr);
}
}
}

43
Zotlabs/Daemon/README.md Normal file
View File

@@ -0,0 +1,43 @@
Daemon (background) Processes
=============================
This directory provides background tasks which are executed by a
command-line process and detached from normal web processing.
Background tasks are invoked by calling
Zotlabs\Daemon\Master::Summon([ $cmd, $arg1, $argn... ]);
The Master class loads the desired command file and passes the arguments.
To create a background task 'Foo' use the following template.
<?php
namespace Zotlabs\Daemon;
class Foo {
static public function run($argc,$argv) {
// do something
}
}
The Master class "summons" the command by creating an executable script
from the provided arguments, then it invokes "Release" to execute the script
detached from web processing. This process calls the static::run() function
with any command line arguments using the traditional argc, argv format.
Please note: These are *real* $argc, $argv variables passed from the command
line, and not the parsed argc() and argv() functions/variables which were
obtained from parsing path components of the request URL by web processes.
Background processes do not emit displayable output except through logs. They
should also not make any assumptions about their HTML and web environment
(as they do not have a web environment), particularly with respect to global
variables such as $_SERVER, $_REQUEST, $_GET, $_POST, $_COOKIES, and $_SESSION.

View File

@@ -0,0 +1,113 @@
<?php
namespace Zotlabs\Daemon;
require_once('include/zot.php');
require_once('include/queue_fn.php');
class Ratenotif {
static public function run($argc,$argv) {
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)
));
$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

@@ -10,7 +10,7 @@ class Hook {
$function = serialize($function);
}
$r = q("SELECT * FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s' and priority = %d and hook_version = %d LIMIT 1",
$r = q("SELECT * FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `fn` = '%s' and priority = %d and hook_version = %d LIMIT 1",
dbesc($hook),
dbesc($file),
dbesc($function),
@@ -23,13 +23,13 @@ class Hook {
// To aid in upgrade and transition, remove old settings for any registered hooks that match in all respects except
// for priority or hook_version
$r = q("DELETE FROM `hook` where `hook` = '%s' and `file` = '%s' and `function` = '%s'",
$r = q("DELETE FROM `hook` where `hook` = '%s' and `file` = '%s' and `fn` = '%s'",
dbesc($hook),
dbesc($file),
dbesc($function)
);
$r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`, `hook_version`) VALUES ( '%s', '%s', '%s', %d, %d )",
$r = q("INSERT INTO `hook` (`hook`, `file`, `fn`, `priority`, `hook_version`) VALUES ( '%s', '%s', '%s', %d, %d )",
dbesc($hook),
dbesc($file),
dbesc($function),
@@ -44,7 +44,7 @@ class Hook {
if(is_array($function)) {
$function = serialize($function);
}
$r = q("DELETE FROM hook WHERE hook = '%s' AND `file` = '%s' AND `function` = '%s' and priority = %d and hook_version = %d",
$r = q("DELETE FROM hook WHERE hook = '%s' AND `file` = '%s' AND `fn` = '%s' and priority = %d and hook_version = %d",
dbesc($hook),
dbesc($file),
dbesc($function),

25
Zotlabs/Lib/AConfig.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
namespace Zotlabs\Lib;
// account configuration storage is built on top of the under-utilised xconfig
class AConfig {
static public function Load($account_id) {
return XConfig::Load('a_' . $account_id);
}
static public function Get($account_id,$family,$key) {
return XConfig::Get('a_' . $account_id,$family,$key);
}
static public function Set($account_id,$family,$key,$value) {
return XConfig::Get('a_' . $account_id,$family,$key,$value);
}
static public function Delete($account_id,$family,$key) {
return XConfig::Delete('a_' . $account_id,$family,$key);
}
}

75
Zotlabs/Lib/AbConfig.php Normal file
View File

@@ -0,0 +1,75 @@
<?php
namespace Zotlabs\Lib;
class AbConfig {
static public function Load($chan,$xhash,$family = '') {
if($family)
$where = sprintf(" and cat = '%s' ",dbesc($family));
$r = q("select * from abconfig where chan = %d and xchan = '%s' $where",
intval($chan),
dbesc($xhash)
);
return $r;
}
static public function Get($chan,$xhash,$family,$key) {
$r = q("select * from abconfig where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' limit 1",
intval($chan),
dbesc($xhash),
dbesc($family),
dbesc($key)
);
if($r) {
return ((preg_match('|^a:[0-9]+:{.*}$|s', $r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
}
return false;
}
static public function Set($chan,$xhash,$family,$key,$value) {
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
if(self::Get($chan,$xhash,$family,$key) === false) {
$r = q("insert into abconfig ( chan, xchan, cat, k, v ) values ( %d, '%s', '%s', '%s', '%s' ) ",
intval($chan),
dbesc($xhash),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
}
else {
$r = q("update abconfig set v = '%s' where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
dbesc($dbvalue),
dbesc($chan),
dbesc($xhash),
dbesc($family),
dbesc($key)
);
}
if($r)
return $value;
return false;
}
static public function Delete($chan,$xhash,$family,$key) {
$r = q("delete from abconfig where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
intval($chan),
dbesc($xhash),
dbesc($family),
dbesc($key)
);
return $r;
}
}

709
Zotlabs/Lib/Apps.php Normal file
View File

@@ -0,0 +1,709 @@
<?php /** @file */
namespace Zotlabs\Lib;
/**
* Apps
*
*/
require_once('include/plugin.php');
require_once('include/channel.php');
class Apps {
static public $installed_system_apps = null;
static public function get_system_apps($translate = true) {
$ret = array();
if(is_dir('apps'))
$files = glob('apps/*.apd');
else
$files = glob('app/*.apd');
if($files) {
foreach($files as $f) {
$x = self::parse_app_description($f,$translate);
if($x) {
$ret[] = $x;
}
}
}
$files = glob('addon/*/*.apd');
if($files) {
foreach($files as $f) {
$path = explode('/',$f);
$plugin = $path[1];
if(plugin_is_installed($plugin)) {
$x = self::parse_app_description($f,$translate);
if($x) {
$ret[] = $x;
}
}
}
}
return $ret;
}
static public function import_system_apps() {
if(! local_channel())
return;
$apps = self::get_system_apps(false);
self::$installed_system_apps = q("select * from app where app_system = 1 and app_channel = %d",
intval(local_channel())
);
if($apps) {
foreach($apps as $app) {
$id = self::check_install_system_app($app);
// $id will be boolean true or false to install an app, or an integer id to update an existing app
if($id === false)
continue;
if($id !== true) {
// if we already installed this app, but it changed, preserve any categories we created
$s = '';
$r = q("select * from term where otype = %d and oid = d",
intval(TERM_OBJ_APP),
intval($id)
);
if($r) {
foreach($r as $t) {
if($s)
$s .= ',';
$s .= $t['term'];
}
$app['categories'] = $s;
}
}
$app['uid'] = local_channel();
$app['guid'] = hash('whirlpool',$app['name']);
$app['system'] = 1;
self::app_install(local_channel(),$app);
}
}
}
/**
* Install the system app if no system apps have been installed, or if a new system app
* is discovered, or if the version of a system app changes.
*/
static public function check_install_system_app($app) {
if((! is_array(self::$installed_system_apps)) || (! count(self::$installed_system_apps))) {
return true;
}
$notfound = true;
foreach(self::$installed_system_apps as $iapp) {
if($iapp['app_id'] == hash('whirlpool',$app['name'])) {
$notfound = false;
if($iapp['app_version'] != $app['version']) {
return intval($iapp['app_id']);
}
}
}
return $notfound;
}
static public function app_name_compare($a,$b) {
return strcmp($a['name'],$b['name']);
}
static public function parse_app_description($f,$translate = true) {
$ret = array();
$baseurl = z_root();
$channel = \App::get_channel();
$address = (($channel) ? $channel['channel_address'] : '');
//future expansion
$observer = \App::get_observer();
$lines = @file($f);
if($lines) {
foreach($lines as $x) {
if(preg_match('/^([a-zA-Z].*?):(.*?)$/ism',$x,$matches)) {
$ret[$matches[1]] = trim(str_replace(array('$baseurl','$nick'),array($baseurl,$address),$matches[2]));
}
}
}
if(! $ret['photo'])
$ret['photo'] = $baseurl . '/' . get_default_profile_photo(80);
$ret['type'] = 'system';
foreach($ret as $k => $v) {
if(strpos($v,'http') === 0)
$ret[$k] = zid($v);
}
if(array_key_exists('desc',$ret))
$ret['desc'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['desc']);
if(array_key_exists('target',$ret))
$ret['target'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['target']);
if(array_key_exists('version',$ret))
$ret['version'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['version']);
if(array_key_exists('requires',$ret)) {
$requires = explode(',',$ret['requires']);
foreach($requires as $require) {
$require = trim(strtolower($require));
switch($require) {
case 'nologin':
if(local_channel())
unset($ret);
break;
case 'admin':
if(! is_site_admin())
unset($ret);
break;
case 'local_channel':
if(! local_channel())
unset($ret);
break;
case 'public_profile':
if(! is_public_profile())
unset($ret);
break;
case 'observer':
if(! $observer)
unset($ret);
break;
default:
if(! (local_channel() && feature_enabled(local_channel(),$require)))
unset($ret);
break;
}
}
}
if($ret) {
if($translate)
self::translate_system_apps($ret);
return $ret;
}
return false;
}
static public function translate_system_apps(&$arr) {
$apps = array(
'Site Admin' => t('Site Admin'),
'Bug Report' => t('Bug Report'),
'View Bookmarks' => t('View Bookmarks'),
'My Chatrooms' => t('My Chatrooms'),
'Connections' => t('Connections'),
'Firefox Share' => t('Firefox Share'),
'Remote Diagnostics' => t('Remote Diagnostics'),
'Suggest Channels' => t('Suggest Channels'),
'Login' => t('Login'),
'Channel Manager' => t('Channel Manager'),
'Grid' => t('Grid'),
'Settings' => t('Settings'),
'Files' => t('Files'),
'Webpages' => t('Webpages'),
'Wiki' => t('Wiki'),
'Channel Home' => t('Channel Home'),
'View Profile' => t('View Profile'),
'Photos' => t('Photos'),
'Events' => t('Events'),
'Directory' => t('Directory'),
'Help' => t('Help'),
'Mail' => t('Mail'),
'Mood' => t('Mood'),
'Poke' => t('Poke'),
'Chat' => t('Chat'),
'Search' => t('Search'),
'Probe' => t('Probe'),
'Suggest' => t('Suggest'),
'Random Channel' => t('Random Channel'),
'Invite' => t('Invite'),
'Features' => t('Features'),
'Language' => t('Language'),
'Post' => t('Post'),
'Profile Photo' => t('Profile Photo')
);
if(array_key_exists($arr['name'],$apps))
$arr['name'] = $apps[$arr['name']];
}
// papp is a portable app
static public function app_render($papp,$mode = 'view') {
/**
* modes:
* view: normal mode for viewing an app via bbcode from a conversation or page
* provides install/update button if you're logged in locally
* list: normal mode for viewing an app on the app page
* no buttons are shown
* edit: viewing the app page in editing mode provides a delete button
*/
$installed = false;
if(! $papp)
return;
if(! $papp['photo'])
$papp['photo'] = z_root() . '/' . get_default_profile_photo(80);
self::translate_system_apps($papp);
$papp['papp'] = self::papp_encode($papp);
if(! strstr($papp['url'],'://'))
$papp['url'] = z_root() . ((strpos($papp['url'],'/') === 0) ? '' : '/') . $papp['url'];
foreach($papp as $k => $v) {
if(strpos($v,'http') === 0 && $k != 'papp')
$papp[$k] = zid($v);
if($k === 'desc')
$papp['desc'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$papp['desc']);
if($k === 'requires') {
$requires = explode(',',$v);
foreach($requires as $require) {
$require = trim(strtolower($require));
switch($require) {
case 'nologin':
if(local_channel())
return '';
break;
case 'admin':
if(! is_site_admin())
return '';
break;
case 'local_channel':
if(! local_channel())
return '';
break;
case 'public_profile':
if(! is_public_profile())
return '';
break;
case 'observer':
$observer = \App::get_observer();
if(! $observer)
return '';
break;
default:
if(! (local_channel() && feature_enabled(local_channel(),$require)))
return '';
break;
}
}
}
}
$hosturl = '';
if(local_channel()) {
$installed = self::app_installed(local_channel(),$papp);
$hosturl = z_root() . '/';
}
elseif(remote_channel()) {
$observer = \App::get_observer();
if($observer && $observer['xchan_network'] === 'zot') {
// some folks might have xchan_url redirected offsite, use the connurl
$x = parse_url($observer['xchan_connurl']);
if($x) {
$hosturl = $x['scheme'] . '://' . $x['host'] . '/';
}
}
}
$install_action = (($installed) ? t('Update') : t('Install'));
return replace_macros(get_markup_template('app.tpl'),array(
'$app' => $papp,
'$hosturl' => $hosturl,
'$purchase' => (($papp['page'] && (! $installed)) ? t('Purchase') : ''),
'$install' => (($hosturl && $mode == 'view') ? $install_action : ''),
'$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''),
'$delete' => ((local_channel() && $installed && $mode == 'edit') ? t('Delete') : '')
));
}
static public function app_install($uid,$app) {
$app['uid'] = $uid;
if(self::app_installed($uid,$app))
$x = self::app_update($app);
else
$x = self::app_store($app);
if($x['success']) {
$r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($x['app_id']),
intval($uid)
);
if($r) {
if(! $r[0]['app_system']) {
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'])
);
build_sync_packet($uid,array('app' => $r[0]));
}
}
}
return $x['app_id'];
}
return false;
}
static public function app_destroy($uid,$app) {
if($uid && $app['guid']) {
$x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($app['guid']),
intval($uid)
);
if($x) {
$x[0]['app_deleted'] = 1;
q("delete from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($x[0]['id'])
);
if($x[0]['app_system']) {
$r = q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
}
else {
$r = q("delete from app where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
// we don't sync system apps - they may be completely different on the other system
build_sync_packet($uid,array('app' => $x));
}
}
}
}
static public function app_installed($uid,$app) {
$r = q("select id from app where app_id = '%s' and app_version = '%s' and app_channel = %d limit 1",
dbesc((array_key_exists('guid',$app)) ? $app['guid'] : ''),
dbesc((array_key_exists('version',$app)) ? $app['version'] : ''),
intval($uid)
);
return(($r) ? true : false);
}
static public function app_list($uid, $deleted = false, $cat = '') {
if($deleted)
$sql_extra = " and app_deleted = 1 ";
else
$sql_extra = " and app_deleted = 0 ";
if($cat) {
$r = q("select oid from term where otype = %d and term = '%s'",
intval(TERM_OBJ_APP),
dbesc($cat)
);
if(! $r)
return $r;
$sql_extra .= " and app.id in ( ";
$s = '';
foreach($r as $rr) {
if($s)
$s .= ',';
$s .= intval($rr['oid']);
}
$sql_extra .= $s . ') ';
}
$r = q("select * from app where app_channel = %d $sql_extra order by app_name asc",
intval($uid)
);
if($r) {
for($x = 0; $x < count($r); $x ++) {
if(! $r[$x]['app_system'])
$r[$x]['type'] = 'personal';
$r[$x]['term'] = q("select * from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($r[$x]['id'])
);
}
}
return($r);
}
static public function app_decode($s) {
$x = base64_decode(str_replace(array('<br />',"\r","\n",' '),array('','','',''),$s));
return json_decode($x,true);
}
static public function app_store($arr) {
// logger('app_store: ' . print_r($arr,true));
$darray = array();
$ret = array('success' => false);
$darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : '');
$darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0);
if((! $darray['app_url']) || (! $darray['app_channel']))
return $ret;
if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
$x = import_xchan_photo($arr['photo'],get_observer_hash(),true);
$arr['photo'] = $x[1];
}
$darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : random_string(). '.' . \App::get_hostname());
$darray['app_sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
$darray['app_author'] = ((x($arr,'author')) ? $arr['author'] : get_observer_hash());
$darray['app_name'] = ((x($arr,'name')) ? escape_tags($arr['name']) : t('Unknown'));
$darray['app_desc'] = ((x($arr,'desc')) ? escape_tags($arr['desc']) : '');
$darray['app_photo'] = ((x($arr,'photo')) ? $arr['photo'] : z_root() . '/' . get_default_profile_photo(80));
$darray['app_version'] = ((x($arr,'version')) ? escape_tags($arr['version']) : '');
$darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
$darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
$darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0);
$darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0);
$created = datetime_convert();
$r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires, app_created, app_edited, app_system, app_deleted ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )",
dbesc($darray['app_id']),
dbesc($darray['app_sig']),
dbesc($darray['app_author']),
dbesc($darray['app_name']),
dbesc($darray['app_desc']),
dbesc($darray['app_url']),
dbesc($darray['app_photo']),
dbesc($darray['app_version']),
intval($darray['app_channel']),
dbesc($darray['app_addr']),
dbesc($darray['app_price']),
dbesc($darray['app_page']),
dbesc($darray['app_requires']),
dbesc($created),
dbesc($created),
intval($darray['app_system']),
intval($darray['app_deleted'])
);
if($r) {
$ret['success'] = true;
$ret['app_id'] = $darray['app_id'];
}
if($arr['categories']) {
$x = q("select id from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($darray['app_id']),
intval($darray['app_channel'])
);
$y = explode(',',$arr['categories']);
if($y) {
foreach($y as $t) {
$t = 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)));
}
}
}
}
return $ret;
}
static public function app_update($arr) {
$darray = array();
$ret = array('success' => false);
$darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : '');
$darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0);
$darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : 0);
if((! $darray['app_url']) || (! $darray['app_channel']) || (! $darray['app_id']))
return $ret;
if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
$x = import_xchan_photo($arr['photo'],get_observer_hash(),true);
$arr['photo'] = $x[1];
}
$darray['app_sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
$darray['app_author'] = ((x($arr,'author')) ? $arr['author'] : get_observer_hash());
$darray['app_name'] = ((x($arr,'name')) ? escape_tags($arr['name']) : t('Unknown'));
$darray['app_desc'] = ((x($arr,'desc')) ? escape_tags($arr['desc']) : '');
$darray['app_photo'] = ((x($arr,'photo')) ? $arr['photo'] : z_root() . '/' . get_default_profile_photo(80));
$darray['app_version'] = ((x($arr,'version')) ? escape_tags($arr['version']) : '');
$darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
$darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
$darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0);
$darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0);
$edited = datetime_convert();
$r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s', app_edited = '%s', app_system = %d, app_deleted = %d where app_id = '%s' and app_channel = %d",
dbesc($darray['app_sig']),
dbesc($darray['app_author']),
dbesc($darray['app_name']),
dbesc($darray['app_desc']),
dbesc($darray['app_url']),
dbesc($darray['app_photo']),
dbesc($darray['app_version']),
dbesc($darray['app_addr']),
dbesc($darray['app_price']),
dbesc($darray['app_page']),
dbesc($darray['app_requires']),
dbesc($edited),
intval($darray['app_system']),
intval($darray['app_deleted']),
dbesc($darray['app_id']),
intval($darray['app_channel'])
);
if($r) {
$ret['success'] = true;
$ret['app_id'] = $darray['app_id'];
}
$x = q("select id from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($darray['app_id']),
intval($darray['app_channel'])
);
if($x) {
q("delete from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($x[0]['id'])
);
if($arr['categories']) {
$y = explode(',',$arr['categories']);
if($y) {
foreach($y as $t) {
$t = 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)));
}
}
}
}
}
return $ret;
}
static public function app_encode($app,$embed = false) {
$ret = array();
$ret['type'] = 'personal';
if($app['app_id'])
$ret['guid'] = $app['app_id'];
if($app['app_id'])
$ret['guid'] = $app['app_id'];
if($app['app_sig'])
$ret['sig'] = $app['app_sig'];
if($app['app_author'])
$ret['author'] = $app['app_author'];
if($app['app_name'])
$ret['name'] = $app['app_name'];
if($app['app_desc'])
$ret['desc'] = $app['app_desc'];
if($app['app_url'])
$ret['url'] = $app['app_url'];
if($app['app_photo'])
$ret['photo'] = $app['app_photo'];
if($app['app_version'])
$ret['version'] = $app['app_version'];
if($app['app_addr'])
$ret['addr'] = $app['app_addr'];
if($app['app_price'])
$ret['price'] = $app['app_price'];
if($app['app_page'])
$ret['page'] = $app['app_page'];
if($app['app_requires'])
$ret['requires'] = $app['app_requires'];
if($app['app_system'])
$ret['system'] = $app['app_system'];
if($app['app_deleted'])
$ret['deleted'] = $app['app_deleted'];
if($app['term']) {
$s = '';
foreach($app['term'] as $t) {
if($s)
$s .= ',';
$s .= $t['term'];
}
$ret['categories'] = $s;
}
if(! $embed)
return $ret;
if(array_key_exists('categories',$ret))
unset($ret['categories']);
$j = json_encode($ret);
return '[app]' . chunk_split(base64_encode($j),72,"\n") . '[/app]';
}
static public function papp_encode($papp) {
return chunk_split(base64_encode(json_encode($papp)),72,"\n");
}
}

51
Zotlabs/Lib/Cache.php Normal file
View File

@@ -0,0 +1,51 @@
<?php /** @file */
namespace Zotlabs\Lib;
/**
* cache api
*/
class Cache {
public static function get($key) {
$key = substr($key,0,254);
$r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
dbesc($key)
);
if ($r)
return $r[0]['v'];
return null;
}
public static function set($key,$value) {
$key = substr($key,0,254);
$r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
dbesc($key)
);
if($r) {
q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
dbesc($value),
dbesc(datetime_convert()),
dbesc($key));
}
else {
q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
dbesc($key),
dbesc($value),
dbesc(datetime_convert()));
}
}
public static function clear() {
q("DELETE FROM cache WHERE updated < '%s'",
dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
}
}

267
Zotlabs/Lib/Chatroom.php Normal file
View File

@@ -0,0 +1,267 @@
<?php
namespace Zotlabs\Lib;
/**
* @brief Chat related functions.
*/
class Chatroom {
/**
* @brief Creates a chatroom.
*
* @param array $channel
* @param array $arr
* @return An associative array containing:
* - success: A boolean
* - message: (optional) A string
*/
static public function create($channel, $arr) {
$ret = array('success' => false);
$name = trim($arr['name']);
if(! $name) {
$ret['message'] = t('Missing room name');
return $ret;
}
$r = q("select cr_id from chatroom where cr_uid = %d and cr_name = '%s' limit 1",
intval($channel['channel_id']),
dbesc($name)
);
if($r) {
$ret['message'] = t('Duplicate room name');
return $ret;
}
$r = q("select count(cr_id) as total from chatroom where cr_aid = %d",
intval($channel['channel_account_id'])
);
if($r)
$limit = service_class_fetch($channel['channel_id'], 'chatrooms');
if(($r) && ($limit !== false) && ($r[0]['total'] >= $limit)) {
$ret['message'] = upgrade_message();
return $ret;
}
if(! array_key_exists('expire', $arr))
$arr['expire'] = 120; // minutes, e.g. 2 hours
$created = datetime_convert();
$x = q("insert into chatroom ( cr_aid, cr_uid, cr_name, cr_created, cr_edited, cr_expire, allow_cid, allow_gid, deny_cid, deny_gid )
values ( %d, %d , '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s' ) ",
intval($channel['channel_account_id']),
intval($channel['channel_id']),
dbesc($name),
dbesc($created),
dbesc($created),
intval($arr['expire']),
dbesc($arr['allow_cid']),
dbesc($arr['allow_gid']),
dbesc($arr['deny_cid']),
dbesc($arr['deny_gid'])
);
if($x)
$ret['success'] = true;
return $ret;
}
static public function destroy($channel,$arr) {
$ret = array('success' => false);
if(intval($arr['cr_id']))
$sql_extra = " and cr_id = " . intval($arr['cr_id']) . " ";
elseif(trim($arr['cr_name']))
$sql_extra = " and cr_name = '" . protect_sprintf(dbesc(trim($arr['cr_name']))) . "' ";
else {
$ret['message'] = t('Invalid room specifier.');
return $ret;
}
$r = q("select * from chatroom where cr_uid = %d $sql_extra limit 1",
intval($channel['channel_id'])
);
if(! $r) {
$ret['message'] = t('Invalid room specifier.');
return $ret;
}
build_sync_packet($channel['channel_id'],array('chatroom' => $r));
q("delete from chatroom where cr_id = %d",
intval($r[0]['cr_id'])
);
if($r[0]['cr_id']) {
q("delete from chatpresence where cp_room = %d",
intval($r[0]['cr_id'])
);
q("delete from chat where chat_room = %d",
intval($r[0]['cr_id'])
);
}
$ret['success'] = true;
return $ret;
}
static public function enter($observer_xchan, $room_id, $status, $client) {
if(! $room_id || ! $observer_xchan)
return;
$r = q("select * from chatroom where cr_id = %d limit 1",
intval($room_id)
);
if(! $r) {
notice( t('Room not found.') . EOL);
return false;
}
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'])
);
if(! $x) {
notice( t('Permission denied.') . EOL);
return false;
}
$limit = service_class_fetch($r[0]['cr_uid'], 'chatters_inroom');
if($limit !== false) {
$y = q("select count(*) as total from chatpresence where cp_room = %d",
intval($room_id)
);
if($y && $y[0]['total'] > $limit) {
notice( t('Room is full') . EOL);
return false;
}
}
if(intval($x[0]['cr_expire'])) {
$r = q("delete from chat where created < %s - INTERVAL %s and chat_room = %d",
db_utcnow(),
db_quoteinterval( intval($x[0]['cr_expire']) . ' MINUTE' ),
intval($x[0]['cr_id'])
);
}
$r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d limit 1",
dbesc($observer_xchan),
intval($room_id)
);
if($r) {
q("update chatpresence set cp_last = '%s' where cp_id = %d and cp_client = '%s'",
dbesc(datetime_convert()),
intval($r[0]['cp_id']),
dbesc($client)
);
return true;
}
$r = q("insert into chatpresence ( cp_room, cp_xchan, cp_last, cp_status, cp_client )
values ( %d, '%s', '%s', '%s', '%s' )",
intval($room_id),
dbesc($observer_xchan),
dbesc(datetime_convert()),
dbesc($status),
dbesc($client)
);
return $r;
}
function leave($observer_xchan, $room_id, $client) {
if(! $room_id || ! $observer_xchan)
return;
$r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d and cp_client = '%s' limit 1",
dbesc($observer_xchan),
intval($room_id),
dbesc($client)
);
if($r) {
q("delete from chatpresence where cp_id = %d",
intval($r[0]['cp_id'])
);
}
return true;
}
static public function roomlist($uid) {
require_once('include/security.php');
$sql_extra = permissions_sql($uid);
$r = q("select allow_cid, allow_gid, deny_cid, deny_gid, cr_name, cr_expire, cr_id, count(cp_id) as cr_inroom from chatroom left join chatpresence on cr_id = cp_room where cr_uid = %d $sql_extra group by cr_name, cr_id order by cr_name",
intval($uid)
);
return $r;
}
static public function list_count($uid) {
require_once('include/security.php');
$sql_extra = permissions_sql($uid);
$r = q("select count(*) as total from chatroom where cr_uid = %d $sql_extra",
intval($uid)
);
return $r[0]['total'];
}
/**
* create a chat message via API.
* It is the caller's responsibility to enter the room.
*/
static public function message($uid, $room_id, $xchan, $text) {
$ret = array('success' => false);
if(! $text)
return;
$sql_extra = permissions_sql($uid);
$r = q("select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
intval($uid),
intval($room_id)
);
if(! $r)
return $ret;
$arr = array(
'chat_room' => $room_id,
'chat_xchan' => $xchan,
'chat_text' => $text
);
call_hooks('chat_message', $arr);
$x = q("insert into chat ( chat_room, chat_xchan, created, chat_text )
values( %d, '%s', '%s', '%s' )",
intval($room_id),
dbesc($xchan),
dbesc(datetime_convert()),
dbesc($arr['chat_text'])
);
$ret['success'] = true;
return $ret;
}
}

166
Zotlabs/Lib/Config.php Normal file
View File

@@ -0,0 +1,166 @@
<?php /** @file */
namespace Zotlabs\Lib;
class Config {
/**
* @brief Loads the hub's configuration from database to a cached storage.
*
* Retrieve a category ($family) of config variables from database to a cached
* storage in the global App::$config[$family].
*
* @param string $family
* The category of the configuration value
*/
static public function Load($family) {
if(! array_key_exists($family, \App::$config))
\App::$config[$family] = array();
if(! array_key_exists('config_loaded', \App::$config[$family])) {
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
if($r !== false) {
if($r) {
foreach($r as $rr) {
$k = $rr['k'];
\App::$config[$family][$k] = $rr['v'];
}
}
\App::$config[$family]['config_loaded'] = true;
}
}
}
/**
* @brief Sets a configuration value for the hub.
*
* Stores a config value ($value) in the category ($family) under the key ($key).
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param mixed $value
* The value to store in the configuration
* @return mixed
* Return the set value, or false if the database update failed
*/
static public function Set($family,$key,$value) {
// manage array value
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
if(get_config($family, $key) === false || (! self::get_from_storage($family, $key))) {
$ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ",
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret) {
\App::$config[$family][$key] = $value;
$ret = $value;
}
return $ret;
}
$ret = q("UPDATE config SET v = '%s' WHERE cat = '%s' AND k = '%s'",
dbesc($dbvalue),
dbesc($family),
dbesc($key)
);
if($ret) {
\App::$config[$family][$key] = $value;
$ret = $value;
}
return $ret;
}
/**
* @brief Get a particular config variable given the category name ($family)
* and a key.
*
* Get a particular config variable from the given category ($family) and the
* $key from a cached storage in App::$config[$family]. If a key is found in the
* DB but does not exist in local config cache, pull it into the cache so we
* do not have to hit the DB again for this item.
*
* Returns false if not set.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @return mixed Return value or false on error or if not set
*/
static public function Get($family,$key) {
if((! array_key_exists($family, \App::$config)) || (! array_key_exists('config_loaded', \App::$config[$family])))
self::Load($family);
if(array_key_exists('config_loaded', \App::$config[$family])) {
if(! array_key_exists($key, \App::$config[$family])) {
return false;
}
return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key]))
? unserialize(\App::$config[$family][$key])
: \App::$config[$family][$key]
);
}
return false;
}
/**
* @brief Deletes the given key from the hub's configuration database.
*
* Removes the configured value from the stored cache in App::$config[$family]
* and removes it from the database.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
static public function Delete($family,$key) {
$ret = false;
if(array_key_exists($family, \App::$config) && array_key_exists($key, \App::$config[$family]))
unset(\App::$config[$family][$key]);
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
dbesc($family),
dbesc($key)
);
return $ret;
}
/**
* @brief Returns a value directly from the database configuration storage.
*
* This function queries directly the database and bypasses the chached storage
* from get_config($family, $key).
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @return mixed
*/
static private function get_from_storage($family,$key) {
$ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
dbesc($family),
dbesc($key)
);
return $ret;
}
}

685
Zotlabs/Lib/Enotify.php Normal file
View File

@@ -0,0 +1,685 @@
<?php
namespace Zotlabs\Lib;
/**
* @brief File with functions and a class for generating system and email notifications.
*/
class Enotify {
/**
* @brief
*
* @param array $params an assoziative array with:
* * \e string \b from_xchan sender xchan hash
* * \e string \b to_xchan recipient xchan hash
* * \e array \b item an assoziative array
* * \e int \b type one of the NOTIFY_* constants from boot.php
* * \e string \b link
* * \e string \b parent_mid
* * \e string \b otype
* * \e string \b verb
* * \e string \b activity
*/
static public function submit($params) {
logger('notification: entry', LOGGER_DEBUG);
// throw a small amount of entropy into the system to breakup duplicates arriving at the same precise instant.
usleep(mt_rand(0, 10000));
if ($params['from_xchan']) {
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($params['from_xchan'])
);
}
if ($params['to_xchan']) {
$y = q("select channel.*, account.* from channel left join account on channel_account_id = account_id
where channel_hash = '%s' and channel_removed = 0 limit 1",
dbesc($params['to_xchan'])
);
}
if ($x & $y) {
$sender = $x[0];
$recip = $y[0];
} else {
logger('notification: no sender or recipient.');
logger('sender: ' . $params['from_xchan']);
logger('recip: ' . $params['to_xchan']);
return;
}
// from here on everything is in the recipients language
push_lang($recip['account_language']); // should probably have a channel language
$banner = t('$Projectname Notification');
$product = t('$projectname'); // PLATFORM_NAME;
$siteurl = z_root();
$thanks = t('Thank You,');
$sitename = get_config('system','sitename');
$site_admin = sprintf( t('%s Administrator'), $sitename);
$sender_name = $product;
$hostname = \App::get_hostname();
if(strpos($hostname,':'))
$hostname = substr($hostname,0,strpos($hostname,':'));
// Do not translate 'noreply' as it must be a legal 7-bit email address
$sender_email = 'noreply' . '@' . $hostname;
$additional_mail_header = "";
if(array_key_exists('item', $params)) {
require_once('include/conversation.php');
// if it's a normal item...
if (array_key_exists('verb', $params['item'])) {
// localize_item() alters the original item so make a copy first
$i = $params['item'];
logger('calling localize');
localize_item($i);
$title = $i['title'];
$body = $i['body'];
$private = (($i['item_private']) || intval($i['item_obscured']));
}
else {
$title = $params['item']['title'];
$body = $params['item']['body'];
}
}
else {
$title = $body = '';
}
// e.g. "your post", "David's photo", etc.
$possess_desc = t('%s <!item_type!>');
if ($params['type'] == NOTIFY_MAIL) {
logger('notification: mail');
$subject = sprintf( t('[Hubzilla:Notify] New mail received at %s'),$sitename);
$preamble = sprintf( t('%1$s, %2$s sent you a new private message at %3$s.'),$recip['channel_name'], $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'];
}
if ($params['type'] == NOTIFY_COMMENT) {
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$itemlink = $params['link'];
// ignore like/unlike activity on posts - they probably require a sepearate notification preference
if (array_key_exists('item',$params) && (! visible_activity($params['item'])))
return;
$parent_mid = $params['parent_mid'];
// 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'])
);
if ($p) {
logger('notification: comment already notified');
pop_lang();
return;
}
// if it's a post figure out who's post it is.
$p = null;
if($params['otype'] === 'item' && $parent_mid) {
$p = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($parent_mid),
intval($recip['channel_id'])
);
}
xchan_query($p);
$item_post_type = item_post_type($p[0]);
// $private = $p[0]['item_private'];
$parent_id = $p[0]['id'];
$parent_item = $p[0];
//$possess_desc = str_replace('<!item_type!>',$possess_desc);
// "a post"
$dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]a %4$s[/zrl]'),
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$itemlink,
$item_post_type);
// "George Bull's post"
if($p)
$dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]%4$s\'s %5$s[/zrl]'),
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$itemlink,
$p[0]['author']['xchan_name'],
$item_post_type);
// "your post"
if($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
$dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]your %4$s[/zrl]'),
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$itemlink,
$item_post_type);
// Some mail softwares relies on subject field for threading.
// So, we cannot have different subjects for notifications of the same thread.
// Before this we have the name of the replier on the subject rendering
// differents subjects for messages on the same thread.
$subject = sprintf( t('[Hubzilla:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
$preamble = sprintf( t('%1$s, %2$s commented on an item/conversation you have been following.'), $recip['channel_name'], $sender['xchan_name']);
$epreamble = $dest_str;
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
}
if($params['type'] == NOTIFY_WALL) {
$subject = sprintf( t('[Hubzilla:Notify] %s posted to your profile wall') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s, %2$s posted to your profile wall at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, %2$s posted to [zrl=%3$s]your wall[/zrl]') ,
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$params['link']);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
}
if ($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'])
);
if ($p) {
logger('enotify: tag: already notified about this post');
pop_lang();
return;
}
$subject = sprintf( t('[Hubzilla:Notify] %s tagged you') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s, %2$s tagged you at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, %2$s [zrl=%3$s]tagged you[/zrl].') ,
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$params['link']);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_POKE) {
$subject = sprintf( t('[Hubzilla:Notify] %1$s poked you') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s, %2$s poked you at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, %2$s [zrl=%2$s]poked you[/zrl].') ,
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$params['link']);
$subject = str_replace('poked', t($params['activity']), $subject);
$preamble = str_replace('poked', t($params['activity']), $preamble);
$epreamble = str_replace('poked', t($params['activity']), $epreamble);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_TAGSHARE) {
$subject = sprintf( t('[Hubzilla:Notify] %s tagged your post') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s, %2$s tagged your post at %3$s') , $recip['channel_name'],$sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, %2$s tagged [zrl=%3$s]your post[/zrl]') ,
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$itemlink);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_INTRO) {
$subject = sprintf( t('[Hubzilla:Notify] Introduction received'));
$preamble = sprintf( t('%1$s, you\'ve received an new connection request from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a new connection request[/zrl] from %3$s.'),
$recip['channel_name'],
$siteurl . '/connections/ifpending',
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
$body = sprintf( t('You may visit their profile at %s'),$sender['xchan_url']);
$sitelink = t('Please visit %s to approve or reject the connection request.');
$tsitelink = sprintf( $sitelink, $siteurl . '/connections/ifpending');
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/connections/ifpending">' . $sitename . '</a>');
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_SUGGEST) {
$subject = sprintf( t('[Hubzilla:Notify] Friend suggestion received'));
$preamble = sprintf( t('%1$s, you\'ve received a friend suggestion from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a friend suggestion[/zrl] for %3$s from %4$s.'),
$recip['channel_name'],
$itemlink,
'[zrl=' . $params['item']['url'] . ']' . $params['item']['name'] . '[/zrl]',
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
$body = t('Name:') . ' ' . $params['item']['name'] . "\n";
$body .= t('Photo:') . ' ' . $params['item']['photo'] . "\n";
$body .= sprintf( t('You may visit their profile at %s'),$params['item']['url']);
$sitelink = t('Please visit %s to approve or reject the suggestion.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_CONFIRM) {
// ?
}
if ($params['type'] == NOTIFY_SYSTEM) {
// ?
}
$h = array(
'params' => $params,
'subject' => $subject,
'preamble' => $preamble,
'epreamble' => $epreamble,
'body' => $body,
'sitelink' => $sitelink,
'sitename' => $sitename,
'tsitelink' => $tsitelink,
'hsitelink' => $hsitelink,
'itemlink' => $itemlink,
'sender' => $sender,
'recipient' => $recip
);
call_hooks('enotify', $h);
$subject = $h['subject'];
$preamble = $h['preamble'];
$epreamble = $h['epreamble'];
$body = $h['body'];
$sitelink = $h['sitelink'];
$tsitelink = $h['tsitelink'];
$hsitelink = $h['hsitelink'];
$itemlink = $h['itemlink'];
require_once('include/html2bbcode.php');
do {
$dups = false;
$hash = random_string();
$r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1",
dbesc($hash));
if ($r)
$dups = true;
} while ($dups === true);
$datarray = array();
$datarray['hash'] = $hash;
$datarray['sender_hash'] = $sender['xchan_hash'];
$datarray['xname'] = $sender['xchan_name'];
$datarray['url'] = $sender['xchan_url'];
$datarray['photo'] = $sender['xchan_photo_s'];
$datarray['created'] = datetime_convert();
$datarray['aid'] = $recip['channel_account_id'];
$datarray['uid'] = $recip['channel_id'];
$datarray['link'] = $itemlink;
$datarray['parent'] = $parent_mid;
$datarray['parent_item'] = $parent_item;
$datarray['ntype'] = $params['type'];
$datarray['verb'] = $params['verb'];
$datarray['otype'] = $params['otype'];
$datarray['abort'] = false;
$datarray['item'] = $params['item'];
call_hooks('enotify_store', $datarray);
if ($datarray['abort']) {
pop_lang();
return;
}
// create notification entry in DB
$seen = 0;
// Mark some notifications as seen right away
// Note! The notification have to be created, because they are used to send emails
// So easiest solution to hide them from Notices is to mark them as seen right away.
// Another option would be to not add them to the DB, and change how emails are handled (probably would be better that way)
$always_show_in_notices = get_pconfig($recip['channel_id'],'system','always_show_in_notices');
if (!$always_show_in_notices) {
if (($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) {
$seen = 1;
}
}
$r = q("insert into notify (hash,xname,url,photo,created,aid,uid,link,parent,seen,ntype,verb,otype)
values('%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,%d,'%s','%s')",
dbesc($datarray['hash']),
dbesc($datarray['xname']),
dbesc($datarray['url']),
dbesc($datarray['photo']),
dbesc($datarray['created']),
intval($datarray['aid']),
intval($datarray['uid']),
dbesc($datarray['link']),
dbesc($datarray['parent']),
intval($seen),
intval($datarray['ntype']),
dbesc($datarray['verb']),
dbesc($datarray['otype'])
);
$r = q("select id from notify where hash = '%s' and uid = %d limit 1",
dbesc($hash),
intval($recip['channel_id'])
);
if ($r) {
$notify_id = $r[0]['id'];
} else {
logger('notification not found.');
pop_lang();
return;
}
$itemlink = z_root() . '/notify/view/' . $notify_id;
$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);
$r = q("update notify set msg = '%s' where id = %d and uid = %d",
dbesc($msg),
intval($notify_id),
intval($datarray['uid'])
);
// send email notification if notification preferences permit
require_once('bbcode.php');
if ((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) {
logger('notification: sending notification email');
$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();
return;
}
$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)));
// use $_SESSION['zid_override'] to force zid() to use
// the recipient address instead of the current observer
$_SESSION['zid_override'] = $recip['channel_address'] . '@' . \App::get_hostname();
$_SESSION['zrl_override'] = z_root() . '/channel/' . $recip['channel_address'];
$textversion = zidify_links($textversion);
$htmlversion = zidify_links($htmlversion);
// unset when done to revert to normal behaviour
unset($_SESSION['zid_override']);
unset($_SESSION['zrl_override']);
$datarray = array();
$datarray['banner'] = $banner;
$datarray['product'] = $product;
$datarray['preamble'] = $preamble;
$datarray['sitename'] = $sitename;
$datarray['siteurl'] = $siteurl;
$datarray['type'] = $params['type'];
$datarray['parent'] = $params['parent_mid'];
$datarray['source_name'] = $sender['xchan_name'];
$datarray['source_link'] = $sender['xchan_url'];
$datarray['source_photo'] = $sender['xchan_photo_s'];
$datarray['uid'] = $recip['channel_id'];
$datarray['username'] = $recip['channel_name'];
$datarray['hsitelink'] = $hsitelink;
$datarray['tsitelink'] = $tsitelink;
$datarray['hitemlink'] = '<a href="' . $itemlink . '">' . $itemlink . '</a>';
$datarray['titemlink'] = $itemlink;
$datarray['thanks'] = $thanks;
$datarray['site_admin'] = $site_admin;
$datarray['title'] = stripslashes($title);
$datarray['htmlversion'] = $htmlversion;
$datarray['textversion'] = $textversion;
$datarray['subject'] = $subject;
$datarray['headers'] = $additional_mail_header;
$datarray['email_secure'] = false;
call_hooks('enotify_mail', $datarray);
// Default to private - don't disclose message contents over insecure channels (such as email)
// Might be interesting to use GPG,PGP,S/MIME encryption instead
// but we'll save that for a clever plugin developer to implement
$private_activity = false;
if (! $datarray['email_secure']) {
switch ($params['type']) {
case NOTIFY_WALL:
case NOTIFY_TAGSELF:
case NOTIFY_POKE:
case NOTIFY_COMMENT:
if (! $private)
break;
$private_activity = true;
case NOTIFY_MAIL:
$datarray['textversion'] = $datarray['htmlversion'] = $datarray['title'] = '';
$datarray['subject'] = preg_replace('/' . preg_quote(t('[Hubzilla:Notify]')) . '/','$0*',$datarray['subject']);
break;
default:
break;
}
}
if ($private_activity
&& intval(get_pconfig($datarray['uid'], 'system', 'ignore_private_notifications'))) {
pop_lang();
return;
}
// load the template for private message notifications
$tpl = get_markup_template('email_notify_html.tpl');
$email_html_body = replace_macros($tpl,array(
'$banner' => $datarray['banner'],
'$notify_icon' => \Zotlabs\Lib\System::get_notify_icon(),
'$product' => $datarray['product'],
'$preamble' => $datarray['preamble'],
'$sitename' => $datarray['sitename'],
'$siteurl' => $datarray['siteurl'],
'$source_name' => $datarray['source_name'],
'$source_link' => $datarray['source_link'],
'$source_photo' => $datarray['source_photo'],
'$username' => $datarray['to_name'],
'$hsitelink' => $datarray['hsitelink'],
'$hitemlink' => $datarray['hitemlink'],
'$thanks' => $datarray['thanks'],
'$site_admin' => $datarray['site_admin'],
'$title' => $datarray['title'],
'$htmlversion' => $datarray['htmlversion'],
));
// load the template for private message notifications
$tpl = get_markup_template('email_notify_text.tpl');
$email_text_body = replace_macros($tpl, array(
'$banner' => $datarray['banner'],
'$product' => $datarray['product'],
'$preamble' => $datarray['preamble'],
'$sitename' => $datarray['sitename'],
'$siteurl' => $datarray['siteurl'],
'$source_name' => $datarray['source_name'],
'$source_link' => $datarray['source_link'],
'$source_photo' => $datarray['source_photo'],
'$username' => $datarray['to_name'],
'$tsitelink' => $datarray['tsitelink'],
'$titemlink' => $datarray['titemlink'],
'$thanks' => $datarray['thanks'],
'$site_admin' => $datarray['site_admin'],
'$title' => $datarray['title'],
'$textversion' => $datarray['textversion'],
));
// logger('text: ' . $email_text_body);
// use the EmailNotification library to send the message
self::send(array(
'fromName' => $sender_name,
'fromEmail' => $sender_email,
'replyTo' => $sender_email,
'toEmail' => $recip['account_email'],
'messageSubject' => $datarray['subject'],
'htmlVersion' => $email_html_body,
'textVersion' => $email_text_body,
'additionalMailHeader' => $datarray['headers'],
));
}
pop_lang();
}
/**
* @brief Send a multipart/alternative message with Text and HTML versions.
*
* @param array $params an assoziative array with:
* * \e string \b fromName name of the sender
* * \e string \b fromEmail email of the sender
* * \e string \b replyTo replyTo address to direct responses
* * \e string \b toEmail destination email address
* * \e string \b messageSubject subject of the message
* * \e string \b htmlVersion html version of the message
* * \e string \b textVersion text only version of the message
* * \e string \b additionalMailHeader additions to the smtp mail header
*/
static public function send($params) {
$fromName = email_header_encode(html_entity_decode($params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
$messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
// generate a mime boundary
$mimeBoundary = rand(0, 9) . "-"
.rand(10000000000, 9999999999) . "-"
.rand(10000000000, 9999999999) . "=:"
.rand(10000, 99999);
// generate a multipart/alternative message header
$messageHeader =
$params['additionalMailHeader'] .
"From: $fromName <{$params['fromEmail']}>\n" .
"Reply-To: $fromName <{$params['replyTo']}>\n" .
"MIME-Version: 1.0\n" .
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
// assemble the final multipart message body with the text and html types included
$textBody = chunk_split(base64_encode($params['textVersion']));
$htmlBody = chunk_split(base64_encode($params['htmlVersion']));
$multipartMessageBody =
"--" . $mimeBoundary . "\n" . // plain text section
"Content-Type: text/plain; charset=UTF-8\n" .
"Content-Transfer-Encoding: base64\n\n" .
$textBody . "\n" .
"--" . $mimeBoundary . "\n" . // text/html section
"Content-Type: text/html; charset=UTF-8\n" .
"Content-Transfer-Encoding: base64\n\n" .
$htmlBody . "\n" .
"--" . $mimeBoundary . "--\n"; // message ending
// send the message
$res = mail(
$params['toEmail'], // send to address
$messageSubject, // subject
$multipartMessageBody, // message body
$messageHeader // message headers
);
logger("notification: enotify::send returns " . $res, LOGGER_DEBUG);
}
static public function format($item) {
$ret = '';
require_once('include/conversation.php');
// Call localize_item with the "brief" flag to get a one line status for activities.
// This should set $item['localized'] to indicate we have a brief summary.
localize_item($item);
if($item_localize) {
$itemem_text = $item['localize'];
}
else {
$itemem_text = (($item['item_thread_top'])
? t('created a new post')
: sprintf( t('commented on %s\'s post'), $item['owner']['xchan_name']));
}
// convert this logic into a json array just like the system notifications
return array(
'notify_link' => $item['llink'],
'name' => $item['author']['xchan_name'],
'url' => $item['author']['xchan_url'],
'photo' => $item['author']['xchan_photo_s'],
'when' => relative_date($item['created']),
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
'message' => strip_tags(bbcode($itemem_text))
);
}
}

165
Zotlabs/Lib/IConfig.php Normal file
View File

@@ -0,0 +1,165 @@
<?php
namespace Zotlabs\Lib;
class IConfig {
static public function Load(&$item) {
return;
}
static public function Get(&$item, $family, $key) {
$is_item = false;
if(is_array($item)) {
$is_item = true;
if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
$item['iconfig'] = array();
if(array_key_exists('item_id',$item))
$iid = $item['item_id'];
else
$iid = $item['id'];
}
elseif(intval($item))
$iid = $item;
if(! $iid)
return false;
if(is_array($item) && array_key_exists('iconfig',$item) && is_array($item['iconfig'])) {
foreach($item['iconfig'] as $c) {
if($c['iid'] == $iid && $c['cat'] == $family && $c['k'] == $key)
return $c['v'];
}
}
$r = q("select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
intval($iid),
dbesc($family),
dbesc($key)
);
if($r) {
$r[0]['v'] = ((preg_match('|^a:[0-9]+:{.*}$|s',$r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
if($is_item)
$item['iconfig'][] = $r[0];
return $r[0]['v'];
}
return false;
}
/**
* IConfig::Set(&$item, $family, $key, $value, $sharing = false);
*
* $item - item array or item id. If passed an array the iconfig meta information is
* added to the item structure (which will need to be saved with item_store eventually).
* If passed an id, the DB is updated, but may not be federated and/or cloned.
* $family - namespace of meta variable
* $key - key of meta variable
* $value - value of meta variable
* $sharing - boolean (default false); if true the meta information is propagated with the item
* to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
* If the meta information is added after delivery and you wish it to be shared, it may be necessary to
* alter the item edited timestamp and invoke the delivery process on the updated item. The edited
* timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
*/
static public function Set(&$item, $family, $key, $value, $sharing = false) {
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
$is_item = false;
$idx = null;
if(is_array($item)) {
$is_item = true;
if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
$item['iconfig'] = array();
elseif($item['iconfig']) {
for($x = 0; $x < count($item['iconfig']); $x ++) {
if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
$idx = $x;
}
}
}
$entry = array('cat' => $family, 'k' => $key, 'v' => $value, 'sharing' => $sharing);
if(is_null($idx))
$item['iconfig'][] = $entry;
else
$item['iconfig'][$idx] = $entry;
return $value;
}
if(intval($item))
$iid = intval($item);
if(! $iid)
return false;
if(self::Get($item, $family, $key) === false) {
$r = q("insert into iconfig( iid, cat, k, v, sharing ) values ( %d, '%s', '%s', '%s', %d ) ",
intval($iid),
dbesc($family),
dbesc($key),
dbesc($dbvalue),
intval($sharing)
);
}
else {
$r = q("update iconfig set v = '%s', sharing = %d where iid = %d and cat = '%s' and k = '%s' ",
dbesc($dbvalue),
intval($sharing),
intval($iid),
dbesc($family),
dbesc($key)
);
}
if(! $r)
return false;
return $value;
}
static public function Delete(&$item, $family, $key) {
$is_item = false;
$idx = null;
if(is_array($item)) {
$is_item = true;
if(is_array($item['iconfig'])) {
for($x = 0; $x < count($item['iconfig']); $x ++) {
if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
unset($item['iconfig'][$x]);
}
}
}
return true;
}
if(intval($item))
$iid = intval($item);
if(! $iid)
return false;
return q("delete from iconfig where iid = %d and cat = '%s' and k = '%s' ",
intval($iid),
dbesc($family),
dbesc($key)
);
}
}

200
Zotlabs/Lib/PConfig.php Normal file
View File

@@ -0,0 +1,200 @@
<?php /** @file */
namespace Zotlabs\Lib;
class PConfig {
/**
* @brief Loads all configuration values of a channel into a cached storage.
*
* All configuration values of the given channel are stored in global cache
* which is available under the global variable App::$config[$uid].
*
* @param string $uid
* The channel_id
* @return void|false Nothing or false if $uid is false
*/
static public function Load($uid) {
if(is_null($uid) || $uid === false)
return false;
if(! array_key_exists($uid, \App::$config))
\App::$config[$uid] = array();
if(! is_array(\App::$config)) {
btlogger('App::$config not an array: ' . $uid);
}
if(! is_array(\App::$config[$uid])) {
btlogger('App::$config[$uid] not an array: ' . $uid);
}
$r = q("SELECT * FROM pconfig WHERE uid = %d",
intval($uid)
);
if($r) {
foreach($r as $rr) {
$k = $rr['k'];
$c = $rr['cat'];
if(! array_key_exists($c, \App::$config[$uid])) {
\App::$config[$uid][$c] = array();
\App::$config[$uid][$c]['config_loaded'] = true;
}
\App::$config[$uid][$c][$k] = $rr['v'];
}
}
}
/**
* @brief Get a particular channel's config variable given the category name
* ($family) and a key.
*
* Get a particular channel's config value from the given category ($family)
* and the $key from a cached storage in App::$config[$uid].
*
* Returns false if not set.
*
* @param string $uid
* The channel_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param boolean $instore (deprecated, without function)
* @return mixed Stored value or false if it does not exist
*/
static public function Get($uid,$family,$key,$instore = false) {
if(is_null($uid) || $uid === false)
return false;
if(! array_key_exists($uid, \App::$config))
self::Load($uid);
if((! array_key_exists($family, \App::$config[$uid])) || (! array_key_exists($key, \App::$config[$uid][$family])))
return false;
return ((! is_array(\App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$uid][$family][$key]))
? unserialize(\App::$config[$uid][$family][$key])
: \App::$config[$uid][$family][$key]
);
}
/**
* @brief Sets a configuration value for a channel.
*
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the channel_id $uid.
*
* @param string $uid
* The channel_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false
*/
static public function Set($uid, $family, $key, $value) {
// this catches subtle errors where this function has been called
// with local_channel() when not logged in (which returns false)
// and throws an error in array_key_exists below.
// we provide a function backtrace in the logs so that we can find
// and fix the calling function.
if(is_null($uid) || $uid === false) {
btlogger('UID is FALSE!', LOGGER_NORMAL, LOG_ERR);
return;
}
// manage array value
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
if(get_pconfig($uid, $family, $key) === false) {
if(! array_key_exists($uid, \App::$config))
\App::$config[$uid] = array();
if(! array_key_exists($family, \App::$config[$uid]))
\App::$config[$uid][$family] = array();
$ret = q("INSERT INTO pconfig ( uid, cat, k, v ) VALUES ( %d, '%s', '%s', '%s' ) ",
intval($uid),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
}
else {
$ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s'",
dbesc($dbvalue),
intval($uid),
dbesc($family),
dbesc($key)
);
}
// keep a separate copy for all variables which were
// set in the life of this page. We need this to
// synchronise channel clones.
if(! array_key_exists('transient', \App::$config[$uid]))
\App::$config[$uid]['transient'] = array();
if(! array_key_exists($family, \App::$config[$uid]['transient']))
\App::$config[$uid]['transient'][$family] = array();
\App::$config[$uid][$family][$key] = $value;
\App::$config[$uid]['transient'][$family][$key] = $value;
if($ret)
return $value;
return $ret;
}
/**
* @brief Deletes the given key from the channel's configuration.
*
* Removes the configured value from the stored cache in App::$config[$uid]
* and removes it from the database.
*
* @param string $uid
* The channel_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
static public function Delete($uid, $family, $key) {
if(is_null($uid) || $uid === false)
return false;
$ret = false;
if(array_key_exists($key, \App::$config[$uid][$family]))
unset(\App::$config[$uid][$family][$key]);
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
intval($uid),
dbesc($family),
dbesc($key)
);
return $ret;
}
}

View File

@@ -1,6 +1,6 @@
<?php
if(class_exists('PermissionDescription')) return;
namespace Zotlabs\Lib;
require_once("include/permissions.php");
require_once("include/language.php");
@@ -78,22 +78,13 @@ class PermissionDescription {
$result = null;
$global_perms = get_perms();
$global_perms = \Zotlabs\Access\Permissions::Perms();
if (array_key_exists($permname, $global_perms)) {
$permDetails = $global_perms[$permname];
$channelPerm = \Zotlabs\Access\PermissionLimits::Get(\App::$channel['channel_id'],$permname);
// It should be OK to always just read the permissions from App::$channel
//
// App::$profile is a union of channel and profile fields.
// The distinction is basically that App::$profile is pointing to the resource
// being observed. App::$channel is referring to the current logged-in channel
// member (if this is a local channel) e.g. the observer. We only show the ACL
// widget to the page owner (observer and observed are the same) so in that case
// I believe either may be safely used here.
$channelPerm = \App::$channel[$permDetails[0]];
$result = new PermissionDescription($permDetails[1], $channelPerm);
$result = new PermissionDescription('', $channelPerm);
} else {
// The acl dialog can handle null arguments, but it shouldn't happen
logger('null PermissionDescription from unknown global permission: ' . $permname ,LOGGER_DEBUG, LOG_ERROR);
@@ -117,11 +108,7 @@ class PermissionDescription {
case PERMS_NETWORK: return t('Anybody in the $Projectname network');
case PERMS_SITE: return sprintf(t('Any account on %s'), \App::get_hostname());
case PERMS_CONTACTS: return t('Any of my connections');
case PERMS_SPECIFIC:
// Because we're describing the permissions of an item with an empty ACL,
// the owner will be the only person able to see it if the permissions are
// set to "only specified connections".
return t('Only me (only specified contacts and me)');
case PERMS_SPECIFIC: return t('Only connections I specifically allow');
case PERMS_AUTHED: return t('Anybody authenticated (could include visitors from other networks)');
case PERMS_PENDING: return t('Any connections including those who haven\'t yet been approved');
default: return $this->fallback_description;
@@ -143,11 +130,7 @@ class PermissionDescription {
case PERMS_NETWORK: return 'fa-share-alt-square'; // fa-share-alt-square is very similiar to the hubzilla logo, but we should create our own logo class to use
case PERMS_SITE: return 'fa-sitemap';
case PERMS_CONTACTS: return 'fa-group';
case PERMS_SPECIFIC:
// Because we're describing the permissions of an item with an empty ACL,
// the owner will be the only person able to see it if the permissions are
// set to "only specified connections".
return 'fa-eye-slash';
case PERMS_SPECIFIC: return 'fa-list';
case PERMS_AUTHED: return '';
case PERMS_PENDING: return '';
default: return '';

View File

@@ -0,0 +1,19 @@
<?php /** @file */
namespace Zotlabs\Lib;
/*
* Abstraction class for dealing with alternate networks (which of course do not exist, hence the abstraction)
*/
abstract class ProtoDriver {
abstract protected function discover($channel,$location);
abstract protected function deliver($item,$channel,$recipients);
abstract protected function collect($channel,$connection);
abstract protected function change_permissions($permissions,$channel,$recipient);
abstract protected function acknowledge_permissions($permissions,$channel,$recipient);
abstract protected function deliver_private($item,$channel,$recipients);
abstract protected function collect_private($channel,$connection);
}

127
Zotlabs/Lib/SuperCurl.php Normal file
View File

@@ -0,0 +1,127 @@
<?php
namespace Zotlabs\Lib;
/**
* @brief wrapper for z_fetch_url() which can be instantiated with several built-in parameters and
* these can be modified and re-used. Useful for CalDAV and other processes which need to authenticate
* and set lots of CURL options (many of which stay the same from one call to the next).
*/
class SuperCurl {
private $auth;
private $url;
private $curlopt = array();
private $headers = null;
public $filepos = 0;
public $filehandle = 0;
public $request_data = '';
private $request_method = 'GET';
private $upload = false;
private $cookies = false;
private function set_data($s) {
$this->request_data = $s;
$this->filepos = 0;
}
public function curl_read($ch,$fh,$size) {
if($this->filepos < 0) {
unset($fh);
return '';
}
$s = substr($this->request_data,$this->filepos,$size);
if(strlen($s) < $size)
$this->filepos = (-1);
else
$this->filepos = $this->filepos + $size;
return $s;
}
public function __construct($opts = array()) {
$this->set($opts);
}
private function set($opts = array()) {
if($opts) {
foreach($opts as $k => $v) {
switch($k) {
case 'http_auth':
$this->auth = $v;
break;
case 'magicauth':
// currently experimental
$this->magicauth = $v;
\Zotlabs\Daemon\Master::Summon([ 'CurlAuth', $v ]);
break;
case 'custom':
$this->request_method = $v;
break;
case 'url':
$this->url = $v;
break;
case 'data':
$this->set_data($v);
if($v) {
$this->upload = true;
}
else {
$this->upload = false;
}
break;
case 'headers':
$this->headers = $v;
break;
default:
$this->curlopts[$k] = $v;
break;
}
}
}
}
function exec() {
$opts = $this->curlopts;
$url = $this->url;
if($this->auth)
$opts['http_auth'] = $this->auth;
if($this->magicauth) {
$opts['cookiejar'] = 'store/[data]/cookie_' . $this->magicauth;
$opts['cookiefile'] = 'store/[data]/cookie_' . $this->magicauth;
$opts['cookie'] = 'PHPSESSID=' . trim(file_get_contents('store/[data]/cookien_' . $this->magicauth));
$c = channelx_by_n($this->magicauth);
if($c)
$url = zid($this->url,$c['channel_address'] . '@' . \App::get_hostname());
}
if($this->custom)
$opts['custom'] = $this->custom;
if($this->headers)
$opts['headers'] = $this->headers;
if($this->upload) {
$opts['upload'] = true;
$opts['infile'] = $this->filehandle;
$opts['infilesize'] = strlen($this->request_data);
$opts['readfunc'] = [ $this, 'curl_read' ] ;
}
$recurse = 0;
return z_fetch_url($this->url,true,$recurse,(($opts) ? $opts : null));
}
}

View File

@@ -1,11 +1,11 @@
<?php
namespace Zotlabs\Project;
namespace Zotlabs\Lib;
class System {
static public function get_platform_name() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['platform_name'])
if(is_array(\App::$config) && is_array(\App::$config['system']) && array_key_exists('platform_name',\App::$config['system']))
return \App::$config['system']['platform_name'];
return PLATFORM_NAME;
}
@@ -43,9 +43,9 @@ class System {
static public function get_server_role() {
if(UNO)
return 'basic';
return 'advanced';
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['server_role'])
return \App::$config['system']['server_role'];
return 'pro';
}
static public function get_std_version() {

781
Zotlabs/Lib/ThreadItem.php Normal file
View File

@@ -0,0 +1,781 @@
<?php /** @file */
namespace Zotlabs\Lib;
require_once('include/text.php');
/**
* A thread item
*/
class ThreadItem {
public $data = array();
private $template = 'conv_item.tpl';
private $comment_box_template = 'comment_item.tpl';
private $commentable = false;
// list of supported reaction emojis - a site can over-ride this via config system.reactions
private $reactions = ['1f60a','1f44f','1f37e','1f48b','1f61e','2665','1f606','1f62e','1f634','1f61c','1f607','1f608'];
private $toplevel = false;
private $children = array();
private $parent = null;
private $conversation = null;
private $redirect_url = null;
private $owner_url = '';
private $owner_photo = '';
private $owner_name = '';
private $wall_to_wall = false;
private $threaded = false;
private $visiting = false;
private $channel = null;
private $display_mode = 'normal';
public function __construct($data) {
$this->data = $data;
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
// Prepare the children
if(count($data['children'])) {
foreach($data['children'] as $item) {
/*
* Only add those that will be displayed
*/
if((! visible_activity($item)) || array_key_exists('author_blocked',$item)) {
continue;
}
$child = new ThreadItem($item);
$this->add_child($child);
}
}
// allow a site to configure the order and content of the reaction emoji list
if($this->toplevel) {
$x = get_config('system','reactions');
if($x && is_array($x) && count($x)) {
$this->reactions = $x;
}
}
}
/**
* Get data in a form usable by a conversation template
*
* Returns:
* _ The data requested on success
* _ false on failure
*/
public function get_template_data($conv_responses, $thread_level=1) {
$result = array();
$item = $this->get_data();
$commentww = '';
$sparkle = '';
$buttons = '';
$dropping = false;
$star = false;
$isstarred = "unstarred fa-star-o";
$indent = '';
$osparkle = '';
$total_children = $this->count_descendants();
$unseen_comments = (($item['real_uid']) ? 0 : $this->count_unseen_descendants());
$conv = $this->get_conversation();
$observer = $conv->get_observer();
$lock = ((($item['item_private'] == 1) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
? t('Private Message')
: false);
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
// allow an exemption for sharing stuff from your private feeds
if($item['author']['xchan_network'] === 'rss')
$shareable = true;
$mode = $conv->get_mode();
if(local_channel() && $observer['xchan_hash'] === $item['author_xchan'])
$edpost = array(z_root()."/editpost/".$item['id'], t("Edit"));
else
$edpost = false;
if($observer['xchan_hash'] == $this->get_data_value('author_xchan')
|| $observer['xchan_hash'] == $this->get_data_value('owner_xchan')
|| $this->get_data_value('uid') == local_channel())
$dropping = true;
if(array_key_exists('real_uid',$item)) {
$edpost = false;
$dropping = false;
}
if($dropping) {
$drop = array(
'dropping' => $dropping,
'delete' => t('Delete'),
);
}
// FIXME
if($observer_is_pageowner) {
$multidrop = array(
'select' => t('Select'),
);
}
$filer = ((($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) ? t("Save to Folder") : false);
$profile_avatar = $item['author']['xchan_photo_m'];
$profile_link = chanlink_url($item['author']['xchan_url']);
$profile_name = $item['author']['xchan_name'];
$location = format_location($item);
$isevent = false;
$attend = null;
$canvote = false;
// process action responses - e.g. like/dislike/attend/agree/whatever
$response_verbs = array('like');
if(feature_enabled($conv->get_profile_owner(),'dislike'))
$response_verbs[] = 'dislike';
if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
$response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno';
$response_verbs[] = 'attendmaybe';
if($this->is_commentable()) {
$isevent = true;
$attend = array( t('I will attend'), t('I will not attend'), t('I might attend'));
}
}
$consensus = (intval($item['item_consensus']) ? true : false);
if($consensus) {
$response_verbs[] = 'agree';
$response_verbs[] = 'disagree';
$response_verbs[] = 'abstain';
if($this->is_commentable()) {
$conlabels = array( t('I agree'), t('I disagree'), t('I abstain'));
$canvote = true;
}
}
if(! feature_enabled($conv->get_profile_owner(),'dislike'))
unset($conv_responses['dislike']);
$responses = get_responses($conv_responses,$response_verbs,$this,$item);
$like_count = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid']] : '');
$like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : '');
if (count($like_list) > MAX_LIKERS) {
$like_list_part = array_slice($like_list, 0, MAX_LIKERS);
array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} else {
$like_list_part = '';
}
$like_button_label = tt('Like','Likes',$like_count,'noun');
if (feature_enabled($conv->get_profile_owner(),'dislike')) {
$dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : '');
$dislike_list = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid'] . '-l'] : '');
$dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
if (count($dislike_list) > MAX_LIKERS) {
$dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} else {
$dislike_list_part = '';
}
}
$showlike = ((x($conv_responses['like'],$item['mid'])) ? format_like($conv_responses['like'][$item['mid']],$conv_responses['like'][$item['mid'] . '-l'],'like',$item['mid']) : '');
$showdislike = ((x($conv_responses['dislike'],$item['mid']) && feature_enabled($conv->get_profile_owner(),'dislike'))
? format_like($conv_responses['dislike'][$item['mid']],$conv_responses['dislike'][$item['mid'] . '-l'],'dislike',$item['mid']) : '');
/*
* We should avoid doing this all the time, but it depends on the conversation mode
* And the conv mode may change when we change the conv, or it changes its mode
* Maybe we should establish a way to be notified about conversation changes
*/
$this->check_wall_to_wall();
if($this->is_toplevel()) {
// FIXME check this permission
if(($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) {
// FIXME we don't need all this stuff, some can be done in the template
$star = array(
'do' => t("Add Star"),
'undo' => t("Remove Star"),
'toggle' => t("Toggle Star Status"),
'classdo' => (intval($item['item_starred']) ? "hidden" : ""),
'classundo' => (intval($item['item_starred']) ? "" : "hidden"),
'isstarred' => (intval($item['item_starred']) ? "starred fa-star" : "unstarred fa-star-o"),
'starred' => t('starred'),
);
}
}
else {
$indent = 'comment';
}
$verified = (intval($item['item_verified']) ? t('Message signature validated') : '');
$forged = ((($item['sig']) && (! intval($item['item_verified']))) ? t('Message signature incorrect') : '');
$unverified = '' ; // (($this->is_wall_to_wall() && (! intval($item['item_verified']))) ? t('Message cannot be verified') : '');
// FIXME - check this permission
if($conv->get_profile_owner() == local_channel()) {
$tagger = array(
'tagit' => t("Add Tag"),
'classtagger' => "",
);
}
$server_role = get_config('system','server_role');
$has_bookmarks = false;
if(is_array($item['term'])) {
foreach($item['term'] as $t) {
if(($server_role != 'basic') && ($t['ttype'] == TERM_BOOKMARK))
$has_bookmarks = true;
}
}
$has_event = false;
if(($item['obj_type'] === ACTIVITY_OBJ_EVENT) && $conv->get_profile_owner() == local_channel())
$has_event = true;
if($this->is_commentable()) {
$like = array( t("I like this \x28toggle\x29"), t("like"));
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
}
if ($shareable)
$share = array( t('Share This'), t('share'));
$dreport = '';
$keep_reports = intval(get_config('system','expire_delivery_reports'));
if($keep_reports === 0)
$keep_reports = 30;
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0)
$dreport = t('Delivery Report');
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
$indent .= ' shiny';
localize_item($item);
$body = prepare_body($item,true);
// $viewthread (below) is only valid in list mode. If this is a channel page, build the thread viewing link
// since we can't depend on llink or plink pointing to the right local location.
$owner_address = substr($item['owner']['xchan_addr'],0,strpos($item['owner']['xchan_addr'],'@'));
$viewthread = $item['llink'];
if($conv->get_mode() === 'channel')
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . $item['mid'];
$comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
$list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : '');
$children = $this->get_children();
$has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);
$tmp_item = array(
'template' => $this->get_template(),
'mode' => $mode,
'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
'body' => $body['html'],
'tags' => $body['tags'],
'categories' => $body['categories'],
'mentions' => $body['mentions'],
'attachments' => $body['attachments'],
'folders' => $body['folders'],
'text' => strip_tags($body['html']),
'id' => $this->get_id(),
'mid' => $item['mid'],
'isevent' => $isevent,
'attend' => $attend,
'consensus' => $consensus,
'conlabels' => $conlabels,
'canvote' => $canvote,
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, $item['author']['xchan_addr']),
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), $item['owner']['xchan_addr']),
'llink' => $item['llink'],
'viewthread' => $viewthread,
'to' => t('to'),
'via' => t('via'),
'wall' => t('Wall-to-Wall'),
'vwall' => t('via Wall-To-Wall:'),
'profile_url' => $profile_link,
'item_photo_menu' => item_photo_menu($item),
'dreport' => $dreport,
'name' => $profile_name,
'thumb' => $profile_avatar,
'osparkle' => $osparkle,
'sparkle' => $sparkle,
'title' => $item['title'],
'title_tosource' => get_pconfig($conv->get_profile_owner(),'system','title_tosource'),
'ago' => relative_date($item['created']),
'app' => $item['app'],
'str_app' => sprintf( t('from %s'), $item['app']),
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''),
'expiretime' => (($item['expires'] !== NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
'lock' => $lock,
'verified' => $verified,
'unverified' => $unverified,
'forged' => $forged,
'location' => $location,
'indent' => $indent,
'owner_url' => $this->get_owner_url(),
'owner_photo' => $this->get_owner_photo(),
'owner_name' => $this->get_owner_name(),
'photo' => $body['photo'],
'event' => $body['event'],
'has_tags' => $has_tags,
'reactions' => $this->reactions,
// Item toolbar buttons
'emojis' => (($this->is_toplevel() && $this->is_commentable() && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
'like' => $like,
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
'share' => $share,
'rawmid' => $item['mid'],
'plink' => get_plink($item),
'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''),
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts')) ? $star : ''),
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing')) ? $filer : ''),
'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''),
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
'drop' => $drop,
'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
// end toolbar buttons
'unseen_comments' => $unseen_comments,
'comment_count' => $total_children,
'comment_count_txt' => $comment_count_txt,
'list_unseen_txt' => $list_unseen_txt,
'markseen' => t('Mark all seen'),
'responses' => $responses,
'like_count' => $like_count,
'like_list' => $like_list,
'like_list_part' => $like_list_part,
'like_button_label' => $like_button_label,
'like_modal_title' => t('Likes','noun'),
'dislike_modal_title' => t('Dislikes','noun'),
'dislike_count' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
'dislike_list' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
'dislike_list_part' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
'dislike_button_label' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
'modal_dismiss' => t('Close'),
'showlike' => $showlike,
'showdislike' => $showdislike,
'comment' => $this->get_comment_box($indent),
'previewing' => ($conv->is_preview() ? ' preview ' : ''),
'wait' => t('Please wait'),
'thread_level' => $thread_level
);
$arr = array('item' => $item, 'output' => $tmp_item);
call_hooks('display_item', $arr);
$result = $arr['output'];
$result['children'] = array();
$nb_children = count($children);
$visible_comments = get_config('system','expanded_comments');
if($visible_comments === false)
$visible_comments = 3;
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
foreach($children as $child) {
$result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1);
}
// Collapse
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
$result['children'][0]['comment_firstcollapsed'] = true;
$result['children'][0]['num_comments'] = $comment_count_txt;
$result['children'][0]['hide_text'] = sprintf( t('%s show all'), '<i class="fa fa-chevron-down"></i>');
if($thread_level > 1) {
$result['children'][$nb_children - 1]['comment_lastcollapsed'] = true;
}
else {
$result['children'][$nb_children - ($visible_comments + 1)]['comment_lastcollapsed'] = true;
}
}
}
$result['private'] = $item['item_private'];
$result['toplevel'] = ($this->is_toplevel() ? 'toplevel_item' : '');
if($this->is_threaded()) {
$result['flatten'] = false;
$result['threaded'] = true;
}
else {
$result['flatten'] = true;
$result['threaded'] = false;
}
return $result;
}
public function get_id() {
return $this->get_data_value('id');
}
public function get_display_mode() {
return $this->display_mode;
}
public function set_display_mode($mode) {
$this->display_mode = $mode;
}
public function is_threaded() {
return $this->threaded;
}
public function set_commentable($val) {
$this->commentable = $val;
foreach($this->get_children() as $child)
$child->set_commentable($val);
}
public function is_commentable() {
return $this->commentable;
}
/**
* Add a child item
*/
public function add_child($item) {
$item_id = $item->get_id();
if(!$item_id) {
logger('[ERROR] Item::add_child : Item has no ID!!', LOGGER_DEBUG);
return false;
}
if($this->get_child($item->get_id())) {
logger('[WARN] Item::add_child : Item already exists ('. $item->get_id() .').', LOGGER_DEBUG);
return false;
}
/*
* Only add what will be displayed
*/
if(activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE)) {
return false;
}
$item->set_parent($this);
$this->children[] = $item;
return end($this->children);
}
/**
* Get a child by its ID
*/
public function get_child($id) {
foreach($this->get_children() as $child) {
if($child->get_id() == $id)
return $child;
}
return null;
}
/**
* Get all our children
*/
public function get_children() {
return $this->children;
}
/**
* Set our parent
*/
protected function set_parent($item) {
$parent = $this->get_parent();
if($parent) {
$parent->remove_child($this);
}
$this->parent = $item;
$this->set_conversation($item->get_conversation());
}
/**
* Remove our parent
*/
protected function remove_parent() {
$this->parent = null;
$this->conversation = null;
}
/**
* Remove a child
*/
public function remove_child($item) {
$id = $item->get_id();
foreach($this->get_children() as $key => $child) {
if($child->get_id() == $id) {
$child->remove_parent();
unset($this->children[$key]);
// Reindex the array, in order to make sure there won't be any trouble on loops using count()
$this->children = array_values($this->children);
return true;
}
}
logger('[WARN] Item::remove_child : Item is not a child ('. $id .').', LOGGER_DEBUG);
return false;
}
/**
* Get parent item
*/
protected function get_parent() {
return $this->parent;
}
/**
* set conversation
*/
public function set_conversation($conv) {
$previous_mode = ($this->conversation ? $this->conversation->get_mode() : '');
$this->conversation = $conv;
// Set it on our children too
foreach($this->get_children() as $child)
$child->set_conversation($conv);
}
/**
* get conversation
*/
public function get_conversation() {
return $this->conversation;
}
/**
* Get raw data
*
* We shouldn't need this
*/
public function get_data() {
return $this->data;
}
/**
* Get a data value
*
* Returns:
* _ value on success
* _ false on failure
*/
public function get_data_value($name) {
if(!isset($this->data[$name])) {
// logger('[ERROR] Item::get_data_value : Item has no value name "'. $name .'".', LOGGER_DEBUG);
return false;
}
return $this->data[$name];
}
/**
* Get template
*/
public function get_template() {
return $this->template;
}
public function set_template($t) {
$this->template = $t;
}
/**
* Check if this is a toplevel post
*/
private function is_toplevel() {
return $this->toplevel;
}
/**
* Count the total of our descendants
*/
private function count_descendants() {
$children = $this->get_children();
$total = count($children);
if($total > 0) {
foreach($children as $child) {
$total += $child->count_descendants();
}
}
return $total;
}
private function count_unseen_descendants() {
$children = $this->get_children();
$total = count($children);
if($total > 0) {
$total = 0;
foreach($children as $child) {
if((! visible_activity($child->data)) || array_key_exists('author_blocked',$child->data)) {
continue;
}
if(intval($child->data['item_unseen']))
$total ++;
}
}
return $total;
}
/**
* Get the template for the comment box
*/
private function get_comment_box_template() {
return $this->comment_box_template;
}
/**
* Get the comment box
*
* Returns:
* _ The comment box string (empty if no comment box)
* _ false on failure
*/
private function get_comment_box($indent) {
if(!$this->is_toplevel() && !get_config('system','thread_allow')) {
return '';
}
$comment_box = '';
$conv = $this->get_conversation();
// logger('Commentable conv: ' . $conv->is_commentable());
if(! $this->is_commentable())
return;
$template = get_markup_template($this->get_comment_box_template());
$observer = $conv->get_observer();
$qc = ((local_channel()) ? get_pconfig(local_channel(),'system','qcomment') : null);
$qcomment = (($qc) ? explode("\n",$qc) : null);
$arr = array('comment_buttons' => '','id' => $this->get_id());
call_hooks('comment_buttons',$arr);
$comment_buttons = $arr['comment_buttons'];
$comment_box = replace_macros($template,array(
'$return_path' => '',
'$threaded' => $this->is_threaded(),
'$jsreload' => '', //(($conv->get_mode() === 'display') ? $_SESSION['return_url'] : ''),
'$type' => (($conv->get_mode() === 'channel') ? 'wall-comment' : 'net-comment'),
'$id' => $this->get_id(),
'$parent' => $this->get_id(),
'$qcomment' => $qcomment,
'$comment_buttons' => $comment_buttons,
'$profile_uid' => $conv->get_profile_owner(),
'$mylink' => $observer['xchan_url'],
'$mytitle' => t('This is you'),
'$myphoto' => $observer['xchan_photo_s'],
'$comment' => t('Comment'),
'$submit' => t('Submit'),
'$edbold' => t('Bold'),
'$editalic' => t('Italic'),
'$eduline' => t('Underline'),
'$edquote' => t('Quote'),
'$edcode' => t('Code'),
'$edimg' => t('Image'),
'$edurl' => t('Insert Link'),
'$edvideo' => t('Video'),
'$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''),
'$indent' => $indent,
'$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false),
'$encrypt' => t('Encrypt text'),
'$cipher' => $conv->get_cipher(),
'$sourceapp' => \App::$sourcename
));
return $comment_box;
}
private function get_redirect_url() {
return $this->redirect_url;
}
/**
* Check if we are a wall to wall item and set the relevant properties
*/
protected function check_wall_to_wall() {
$conv = $this->get_conversation();
$this->wall_to_wall = false;
$this->owner_url = '';
$this->owner_photo = '';
$this->owner_name = '';
if($conv->get_mode() === 'channel')
return;
if($this->is_toplevel() && ($this->get_data_value('author_xchan') != $this->get_data_value('owner_xchan'))) {
$this->owner_url = chanlink_url($this->data['owner']['xchan_url']);
$this->owner_photo = $this->data['owner']['xchan_photo_m'];
$this->owner_name = $this->data['owner']['xchan_name'];
$this->wall_to_wall = true;
}
}
private function is_wall_to_wall() {
return $this->wall_to_wall;
}
private function get_owner_url() {
return $this->owner_url;
}
private function get_owner_photo() {
return $this->owner_photo;
}
private function get_owner_name() {
return $this->owner_name;
}
private function is_visiting() {
return $this->visiting;
}
}

View File

@@ -0,0 +1,220 @@
<?php /** @file */
namespace Zotlabs\Lib;
require_once('boot.php');
require_once('include/text.php');
require_once('include/items.php');
/**
* A list of threads
*
*/
class ThreadStream {
private $threads = array();
private $mode = null;
private $observer = null;
private $writable = false;
private $commentable = false;
private $profile_owner = 0;
private $preview = false;
private $prepared_item = '';
private $cipher = 'aes256';
// $prepared_item is for use by alternate conversation structures such as photos
// wherein we've already prepared a top level item which doesn't look anything like
// a normal "post" item
public function __construct($mode, $preview, $prepared_item = '') {
$this->set_mode($mode);
$this->preview = $preview;
$this->prepared_item = $prepared_item;
$c = ((local_channel()) ? get_pconfig(local_channel(),'system','default_cipher') : '');
if($c)
$this->cipher = $c;
}
/**
* Set the mode we'll be displayed on
*/
private function set_mode($mode) {
if($this->get_mode() == $mode)
return;
$this->observer = \App::get_observer();
$ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
switch($mode) {
case 'network':
$this->profile_owner = local_channel();
$this->writable = true;
break;
case 'channel':
$this->profile_owner = \App::$profile['profile_uid'];
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
break;
case 'display':
// 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');
break;
case 'page':
$this->profile_owner = \App::$profile['uid'];
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
break;
default:
logger('[ERROR] Conversation::set_mode : Unhandled mode ('. $mode .').', LOGGER_DEBUG);
return false;
break;
}
$this->mode = $mode;
}
/**
* Get mode
*/
public function get_mode() {
return $this->mode;
}
/**
* Check if page is writable
*/
public function is_writable() {
return $this->writable;
}
public function is_commentable() {
return $this->commentable;
}
/**
* Check if page is a preview
*/
public function is_preview() {
return $this->preview;
}
/**
* Get profile owner
*/
public function get_profile_owner() {
return $this->profile_owner;
}
public function set_profile_owner($uid) {
$this->profile_owner = $uid;
$mode = $this->get_mode();
$this->mode = null;
$this->set_mode($mode);
}
public function get_observer() {
return $this->observer;
}
public function get_cipher() {
return $this->cipher;
}
/**
* Add a thread to the conversation
*
* Returns:
* _ The inserted item on success
* _ false on failure
*/
public function add_thread($item) {
$item_id = $item->get_id();
if(!$item_id) {
logger('Item has no ID!!', LOGGER_DEBUG, LOG_ERR);
return false;
}
if($this->get_thread($item->get_id())) {
logger('Thread already exists ('. $item->get_id() .').', LOGGER_DEBUG, LOG_WARNING);
return false;
}
/*
* 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);
if(intval($item->get_data_value('item_nocomment'))) {
$item->set_commentable(false);
}
elseif(($this->observer) && (! $item->is_commentable())) {
if((array_key_exists('owner',$item->data)) && intval($item->data['owner']['abook_self']))
$item->set_commentable(perm_is_allowed($this->profile_owner,$this->observer['xchan_hash'],'post_comments'));
else
$item->set_commentable(can_comment_on_post($this->observer['xchan_hash'],$item->data));
}
}
require_once('include/channel.php');
$item->set_conversation($this);
$this->threads[] = $item;
return end($this->threads);
}
/**
* Get data in a form usable by a conversation template
*
* We should find a way to avoid using those arguments (at least most of them)
*
* Returns:
* _ The data requested on success
* _ false on failure
*/
public function get_template_data($conv_responses) {
$result = array();
foreach($this->threads as $item) {
if(($item->get_data_value('id') == $item->get_data_value('parent')) && $this->prepared_item) {
$item_data = $this->prepared_item;
}
else {
$item_data = $item->get_template_data($conv_responses);
}
if(!$item_data) {
logger('Failed to get item template data ('. $item->get_id() .').', LOGGER_DEBUG, LOG_ERR);
return false;
}
$result[] = $item_data;
}
return $result;
}
/**
* Get a thread based on its item id
*
* Returns:
* _ The found item on success
* _ false on failure
*/
private function get_thread($id) {
foreach($this->threads as $item) {
if($item->get_id() == $id)
return $item;
}
return false;
}
}

160
Zotlabs/Lib/XConfig.php Normal file
View File

@@ -0,0 +1,160 @@
<?php
namespace Zotlabs\Lib;
class XConfig {
/**
* @brief Loads a full xchan's configuration into a cached storage.
*
* All configuration values of the given observer hash are stored in global
* cache which is available under the global variable App::$config[$xchan].
*
* @param string $xchan
* The observer's hash
* @return void|false Returns false if xchan is not set
*/
static public function Load($xchan) {
if(! $xchan)
return false;
if(! array_key_exists($xchan, \App::$config))
\App::$config[$xchan] = array();
$r = q("SELECT * FROM xconfig WHERE xchan = '%s'",
dbesc($xchan)
);
if($r) {
foreach($r as $rr) {
$k = $rr['k'];
$c = $rr['cat'];
if(! array_key_exists($c, \App::$config[$xchan])) {
\App::$config[$xchan][$c] = array();
\App::$config[$xchan][$c]['config_loaded'] = true;
}
\App::$config[$xchan][$c][$k] = $rr['v'];
}
}
}
/**
* @brief Get a particular observer's config variable given the category
* name ($family) and a key.
*
* Get a particular observer's config value from the given category ($family)
* and the $key from a cached storage in App::$config[$xchan].
*
* Returns false if not set.
*
* @param string $xchan
* The observer's hash
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @return mixed Stored $value or false if it does not exist
*/
static public function Get($xchan, $family, $key) {
if(! $xchan)
return false;
if(! array_key_exists($xchan, \App::$config))
load_xconfig($xchan);
if((! array_key_exists($family, \App::$config[$xchan])) || (! array_key_exists($key, \App::$config[$xchan][$family])))
return false;
return ((! is_array(\App::$config[$xchan][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$xchan][$family][$key]))
? unserialize(\App::$config[$xchan][$family][$key])
: \App::$config[$xchan][$family][$key]
);
}
/**
* @brief Sets a configuration value for an observer.
*
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the observer's $xchan hash.
*
*
* @param string $xchan
* The observer's hash
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false
*/
static public function Set($xchan, $family, $key, $value) {
// manage array value
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
if(self::Get($xchan, $family, $key) === false) {
if(! array_key_exists($xchan, \App::$config))
\App::$config[$xchan] = array();
if(! array_key_exists($family, \App::$config[$xchan]))
\App::$config[$xchan][$family] = array();
$ret = q("INSERT INTO xconfig ( xchan, cat, k, v ) VALUES ( '%s', '%s', '%s', '%s' ) ",
dbesc($xchan),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
}
else {
$ret = q("UPDATE xconfig SET v = '%s' WHERE xchan = '%s' and cat = '%s' AND k = '%s'",
dbesc($dbvalue),
dbesc($xchan),
dbesc($family),
dbesc($key)
);
}
\App::$config[$xchan][$family][$key] = $value;
if($ret)
return $value;
return $ret;
}
/**
* @brief Deletes the given key from the observer's config.
*
* Removes the configured value from the stored cache in App::$config[$xchan]
* and removes it from the database.
*
* @param string $xchan
* The observer's hash
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
static public function Delete($xchan, $family, $key) {
if(x(\App::$config[$xchan][$family], $key))
unset(\App::$config[$xchan][$family][$key]);
$ret = q("DELETE FROM xconfig WHERE xchan = '%s' AND cat = '%s' AND k = '%s'",
dbesc($xchan),
dbesc($family),
dbesc($key)
);
return $ret;
}
}

30
Zotlabs/Lib/ZotDriver.php Normal file
View File

@@ -0,0 +1,30 @@
<?php /** @file */
namespace Zotlabs\Lib;
class ZotDriver extends ProtoDriver {
protected function discover($channel,$location) {
}
protected function deliver($item,$channel,$recipients) {
}
protected function collect($channel,$connection) {
}
protected function change_permissions($permissions,$channel,$recipient) {
}
protected function acknowledge_permissions($permissions,$channel,$recipient) {
}
protected function deliver_private($item,$channel,$recipients) {
}
protected function collect_private($channel,$connection) {
}
}

View File

@@ -18,7 +18,7 @@ class Achievements extends \Zotlabs\Web\Controller {
$profile = 0;
$profile = argv(1);
profile_load($a,$which,$profile);
profile_load($which,$profile);
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)

View File

@@ -1,7 +1,18 @@
<?php
namespace Zotlabs\Module;
/* ACL selector json backend */
/*
* ACL selector json backend
* This module provides JSON lists of connections and local/remote channels
* (xchans) to populate various tools such as the ACL (AccessControlList) popup
* and various auto-complete functions (such as email recipients, search, and
* mention targets.
* There are two primary output structural formats. One for the ACL widget and
* the other for auto-completion.
* Many of the behaviour variations are triggered on the use of single character keys
* however this functionality has grown in an ad-hoc manner and has gotten quite messy over time.
*/
require_once("include/acl_selectors.php");
require_once("include/group.php");
@@ -10,40 +21,80 @@ class Acl extends \Zotlabs\Web\Controller {
function init(){
// logger('mod_acl: ' . print_r($_REQUEST,true));
// logger('mod_acl: ' . print_r($_REQUEST,true));
$start = (x($_REQUEST,'start')?$_REQUEST['start']:0);
$count = (x($_REQUEST,'count')?$_REQUEST['count']:100);
$search = (x($_REQUEST,'search')?$_REQUEST['search']:"");
$type = (x($_REQUEST,'type')?$_REQUEST['type']:"");
$noforums = (x($_REQUEST,'n') ? $_REQUEST['n'] : false);
$start = (x($_REQUEST,'start') ? $_REQUEST['start'] : 0);
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 500);
$search = (x($_REQUEST,'search') ? $_REQUEST['search'] : '');
$type = (x($_REQUEST,'type') ? $_REQUEST['type'] : '');
$noforums = (x($_REQUEST,'n') ? $_REQUEST['n'] : false);
// $type =
// '' => standard ACL request
// 'g' => Groups only ACL request
// 'c' => Connections only ACL request or editor (textarea) mention request
// $_REQUEST['search'] contains ACL search text.
// $type =
// 'm' => autocomplete private mail recipient (checks post_mail permission)
// 'a' => autocomplete connections (mod_connections, mod_poke, mod_sources, mod_photos)
// 'x' => nav search bar autocomplete (match any xchan)
// $_REQUEST['query'] contains autocomplete search text.
// List of channels whose connections to also suggest, e.g. currently viewed channel or channels mentioned in a post
// List of channels whose connections to also suggest,
// e.g. currently viewed channel or channels mentioned in a post
$extra_channels = (x($_REQUEST,'extra_channels') ? $_REQUEST['extra_channels'] : array());
// For use with jquery.autocomplete for private mail completion
// The different autocomplete libraries use different names for the search text
// parameter. Internaly we'll use $search to represent the search text no matter
// what request variable it was attached to.
if(x($_REQUEST,'query') && strlen($_REQUEST['query'])) {
if(! $type)
$type = 'm';
if(array_key_exists('query',$_REQUEST)) {
$search = $_REQUEST['query'];
}
if(!(local_channel()))
if(!($type == 'x' || $type == 'c'))
killme();
if ($search != "") {
if( (! local_channel()) && (! ($type == 'x' || $type == 'c')))
killme();
$permitted = [];
if(in_array($type, [ 'm', 'a', 'c' ])) {
// These queries require permission checking. We'll create a simple array of xchan_hash for those with
// the requisite permissions which we can check against.
$x = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = '%s' and v = 1",
intval(local_channel()),
dbesc(($type === 'm') ? 'post_mail' : 'tag_deliver')
);
$permitted = ids_to_array($x,'xchan');
}
if($search) {
$sql_extra = " AND `name` LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
$sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc($search) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
// This horrible mess is needed because position also returns 0 if nothing is found. W/ould be MUCH easier if it instead returned a very large value
// Otherwise we could just order by LEAST(POSITION($search IN xchan_name),POSITION($search IN xchan_addr)).
$order_extra2 = "CASE WHEN xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) ." then POSITION('".dbesc($search)."' IN xchan_name) else position('".dbesc($search)."' IN xchan_addr) end, ";
// This horrible mess is needed because position also returns 0 if nothing is found.
// Would be MUCH easier if it instead returned a very large value
// Otherwise we could just
// order by LEAST(POSITION($search IN xchan_name),POSITION($search IN xchan_addr)).
$order_extra2 = "CASE WHEN xchan_name LIKE "
. protect_sprintf( "'%" . dbesc($search) . "%'" )
. " then POSITION('" . dbesc($search)
. "' IN xchan_name) else position('" . dbesc($search) . "' IN xchan_addr) end, ";
$col = ((strpos($search,'@') !== false) ? 'xchan_addr' : 'xchan_name' );
$sql_extra3 = "AND $col like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
} else {
}
else {
$sql_extra = $sql_extra2 = $sql_extra3 = "";
}
@@ -51,36 +102,38 @@ class Acl extends \Zotlabs\Web\Controller {
$groups = array();
$contacts = array();
if ($type=='' || $type=='g'){
if($type == '' || $type == 'g') {
$r = q("SELECT `groups`.`id`, `groups`.`hash`, `groups`.`name`
FROM `groups`,`group_member`
WHERE `groups`.`deleted` = 0 AND `groups`.`uid` = %d
AND `group_member`.`gid`=`groups`.`id`
$r = q("SELECT groups.id, groups.hash, groups.gname
FROM groups,group_member
WHERE groups.deleted = 0 AND groups.uid = %d
AND group_member.gid=groups.id
$sql_extra
GROUP BY `groups`.`id`
ORDER BY `groups`.`name`
GROUP BY groups.id
ORDER BY groups.gname
LIMIT %d OFFSET %d",
intval(local_channel()),
intval($count),
intval($start)
);
foreach($r as $g){
// logger('acl: group: ' . $g['name'] . ' members: ' . group_get_members_xchan($g['id']));
$groups[] = array(
"type" => "g",
"photo" => "images/twopeople.png",
"name" => $g['name'],
"id" => $g['id'],
"xid" => $g['hash'],
"uids" => group_get_members_xchan($g['id']),
"link" => ''
);
if($r) {
foreach($r as $g){
// logger('acl: group: ' . $g['gname'] . ' members: ' . group_get_members_xchan($g['id']));
$groups[] = array(
"type" => "g",
"photo" => "images/twopeople.png",
"name" => $g['gname'],
"id" => $g['id'],
"xid" => $g['hash'],
"uids" => group_get_members_xchan($g['id']),
"link" => ''
);
}
}
}
if ($type=='' || $type=='c') {
if($type == '' || $type == 'c') {
$extra_channels_sql = '';
// Only include channels who allow the observer to view their permissions
foreach($extra_channels as $channel) {
@@ -94,13 +147,40 @@ class Acl extends \Zotlabs\Web\Controller {
if(local_channel()) {
if($extra_channels_sql != '')
$extra_channels_sql = " OR (abook_channel IN ($extra_channels_sql)) and abook_hidden = 0 ";
$r2 = null;
$r1 = q("select * from atoken where atoken_uid = %d",
intval(local_channel())
);
if($r1) {
require_once('include/security.php');
$r2 = array();
foreach($r1 as $rr) {
$x = atoken_xchan($rr);
$r2[] = [
'id' => 'a' . $rr['atoken_id'] ,
'hash' => $x['xchan_hash'],
'name' => $x['xchan_name'],
'micro' => $x['xchan_photo_m'],
'url' => z_root(),
'nick' => $x['xchan_addr'],
'abook_their_perms' => 0,
'abook_flags' => 0,
'abook_self' => 0
];
}
}
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags, abook_self
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, xchan_pubforum, abook_flags, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash
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);
}
else { // Visitors
$r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
@@ -158,18 +238,26 @@ class Acl extends \Zotlabs\Web\Controller {
}
}
elseif($type == 'm') {
$r = q("SELECT xchan_hash as id, xchan_name as name, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
$r = array();
$z = q("SELECT xchan_hash as hash, xchan_name as name, 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 ( (abook_their_perms = null) or (abook_their_perms & %d )>0)
WHERE abook_channel = %d
and xchan_deleted = 0
$sql_extra3
ORDER BY `xchan_name` ASC ",
intval(local_channel()),
intval(PERMS_W_MAIL)
ORDER BY xchan_name ASC ",
intval(local_channel())
);
if($z) {
foreach($z as $zz) {
if(in_array($zz['hash'],$permitted)) {
$r[] = $zz;
}
}
}
}
elseif(($type == 'a') || ($type == 'p')) {
elseif($type == 'a') {
$r = q("SELECT abook_id as id, xchan_name as name, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_network as network, xchan_url as url, xchan_addr as attag , abook_their_perms FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d
@@ -204,14 +292,14 @@ class Acl extends \Zotlabs\Web\Controller {
else
$r = array();
if(count($r)) {
if($r) {
foreach($r as $g){
// remove RSS feeds from ACLs - they are inaccessible
if(strpos($g['hash'],'/') && $type != 'a')
continue;
if(($g['abook_their_perms'] & PERMS_W_TAGWALL) && $type == 'c' && (! $noforums)) {
if(in_array($g['hash'],$permitted) && $type == 'c' && (! $noforums)) {
$contacts[] = array(
"type" => "c",
"photo" => "images/twopeople.png",
@@ -260,7 +348,7 @@ class Acl extends \Zotlabs\Web\Controller {
// logger('navbar_complete');
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
if(observer_prohibited()) {
return;
}
@@ -294,7 +382,7 @@ class Acl extends \Zotlabs\Web\Controller {
$url = $directory['url'] . '/dirsearch';
}
$count = (x($_REQUEST,'count')?$_REQUEST['count']:100);
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
if($url) {
$query = $url . '?f=' ;
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode($search) : '');

View File

@@ -32,8 +32,8 @@ class Admin extends \Zotlabs\Web\Controller {
case 'site':
$this->admin_page_site_post($a);
break;
case 'users':
$this->admin_page_users_post($a);
case 'accounts':
$this->admin_page_accounts_post($a);
break;
case 'channels':
$this->admin_page_channels_post($a);
@@ -127,8 +127,8 @@ class Admin extends \Zotlabs\Web\Controller {
case 'site':
$o = $this->admin_page_site($a);
break;
case 'users':
$o = $this->admin_page_users($a);
case 'accounts':
$o = $this->admin_page_accounts($a);
break;
case 'channels':
$o = $this->admin_page_channels($a);
@@ -872,20 +872,20 @@ class Admin extends \Zotlabs\Web\Controller {
}
/**
* @brief Handle POST actions on users admin page.
* @brief Handle POST actions on accounts admin page.
*
* This function is called when on the admin user/account page the form was
* submitted to handle multiple operations at once. If one of the icons next
* to an entry are pressed the function admin_page_users() will handle this.
* to an entry are pressed the function admin_page_accounts() will handle this.
*
* @param App $a
*/
function admin_page_users_post($a) {
function admin_page_accounts_post($a) {
$pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() );
$users = ( x($_POST, 'user') ? $_POST['user'] : array() );
$blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : array() );
check_form_security_token_redirectOnErr('/admin/users', 'admin_users');
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts');
// change to switch structure?
// account block/unblock button was submitted
@@ -901,8 +901,7 @@ class Admin extends \Zotlabs\Web\Controller {
notice( sprintf( tt("%s account blocked/unblocked", "%s account blocked/unblocked", count($users)), count($users)) );
}
// account delete button was submitted
if (x($_POST, 'page_users_delete')) {
require_once('include/Contact.php');
if (x($_POST, 'page_accounts_delete')) {
foreach ($users as $uid){
account_remove($uid, true, false);
}
@@ -921,20 +920,20 @@ class Admin extends \Zotlabs\Web\Controller {
}
}
goaway(z_root() . '/admin/users' );
goaway(z_root() . '/admin/accounts' );
}
/**
* @brief Generate users admin page and handle single item operations.
* @brief Generate accounts admin page and handle single item operations.
*
* This function generates the users/account admin page and handles the actions
* This function generates the accounts/account admin page and handles the actions
* if an icon next to an entry was clicked. If several items were selected and
* the form was submitted it is handled by the function admin_page_users_post().
* the form was submitted it is handled by the function admin_page_accounts_post().
*
* @param App &$a
* @return string
*/
function admin_page_users(&$a){
function admin_page_accounts(&$a){
if (argc() > 2) {
$uid = argv(3);
$account = q("SELECT * FROM account WHERE account_id = %d",
@@ -943,15 +942,14 @@ class Admin extends \Zotlabs\Web\Controller {
if (! $account) {
notice( t('Account not found') . EOL);
goaway(z_root() . '/admin/users' );
goaway(z_root() . '/admin/accounts' );
}
check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts', 't');
switch (argv(2)){
case 'delete':
// delete user
require_once('include/Contact.php');
account_remove($uid,true,false);
notice( sprintf(t("Account '%s' deleted"), $account[0]['account_email']) . EOL);
@@ -974,7 +972,7 @@ class Admin extends \Zotlabs\Web\Controller {
break;
}
goaway(z_root() . '/admin/users' );
goaway(z_root() . '/admin/accounts' );
}
/* get pending */
@@ -982,7 +980,7 @@ class Admin extends \Zotlabs\Web\Controller {
intval(ACCOUNT_PENDING)
);
/* get users */
/* get accounts */
$total = q("SELECT count(*) as total FROM account");
if (count($total)) {
@@ -990,22 +988,20 @@ class Admin extends \Zotlabs\Web\Controller {
\App::set_pager_itemspage(100);
}
// We'll still need to link email addresses to admin/users/channels or some such, but this bit doesn't exist yet.
// That's where we need to be doing last post/channel flags/etc, not here.
$serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : '');
$key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'account_id');
$dir = 'asc';
if(array_key_exists('dir',$_REQUEST))
$dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc');
$base = z_root() . '/admin/accounts?f=';
$odir = (($dir === 'asc') ? '0' : '1');
$order = " order by account_email asc ";
if($_REQUEST['order'] === 'expires')
$order = " order by account_expires desc ";
if($_REQUEST['order'] === 'created')
$order = " order by account_created desc ";
$users = q("SELECT `account_id` , `account_email`, `account_lastlog`, `account_created`, `account_expires`, " . "`account_service_class`, ( account_flags & %d )>0 as `blocked`, " .
$users = q("SELECT `account_id` , `account_email`, `account_lastlog`, `account_created`, `account_expires`, " . "`account_service_class`, ( account_flags & %d ) > 0 as `blocked`, " .
"(SELECT %s FROM channel as ch " .
"WHERE ch.channel_account_id = ac.account_id and ch.channel_removed = 0 ) as `channels` " .
"FROM account as ac where true $serviceclass $order limit %d offset %d ",
"FROM account as ac where true $serviceclass order by $key $dir limit %d offset %d ",
intval(ACCOUNT_BLOCKED),
db_concat('ch.channel_address', ' '),
intval(\App::$pager['itemspage']),
@@ -1028,14 +1024,14 @@ class Admin extends \Zotlabs\Web\Controller {
// }
// $users = array_map("_setup_users", $users);
$t = get_markup_template('admin_users.tpl');
$t = get_markup_template('admin_accounts.tpl');
$o = replace_macros($t, array(
// strings //
'$title' => t('Administration'),
'$page' => t('Users'),
'$page' => t('Accounts'),
'$submit' => t('Submit'),
'$select_all' => t('select all'),
'$h_pending' => t('User registrations waiting for confirm'),
'$h_pending' => t('Registrations waiting for confirm'),
'$th_pending' => array( t('Request date'), t('Email') ),
'$no_pending' => t('No registrations.'),
'$approve' => t('Approve'),
@@ -1043,14 +1039,22 @@ class Admin extends \Zotlabs\Web\Controller {
'$delete' => t('Delete'),
'$block' => t('Block'),
'$unblock' => t('Unblock'),
'$h_users' => t('Users'),
'$th_users' => array( t('ID'), t('Email'), t('All Channels'), t('Register date'), t('Last login'), t('Expires'), t('Service Class')),
'$odir' => $odir,
'$base' => $base,
'$h_users' => t('Accounts'),
'$th_users' => array(
[ t('ID'), 'account_id' ],
[ t('Email'), 'account_email' ],
[ t('All Channels'), 'channels' ],
[ t('Register date'), 'account_created' ],
[ t('Last login'), 'account_lastlog' ],
[ t('Expires'), 'account_expires' ],
[ t('Service Class'), 'account_service_class'] ),
'$confirm_delete_multi' => t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?'),
'$confirm_delete' => t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?'),
'$form_security_token' => get_form_security_token("admin_users"),
'$form_security_token' => get_form_security_token("admin_accounts"),
// values //
'$baseurl' => z_root(),
@@ -1082,7 +1086,7 @@ class Admin extends \Zotlabs\Web\Controller {
intval(PAGE_CENSORED),
intval( $uid )
);
proc_run('php','include/directory.php',$uid,'nopush');
\Zotlabs\Daemon\Master::Summon(array('Directory',$uid,'nopush'));
}
notice( sprintf( tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)) );
}
@@ -1096,7 +1100,6 @@ class Admin extends \Zotlabs\Web\Controller {
notice( sprintf( tt("%s channel code allowed/disallowed", "%s channels code allowed/disallowed", count($channels)), count($channels)) );
}
if (x($_POST,'page_channels_delete')){
require_once("include/Contact.php");
foreach($channels as $uid){
channel_remove($uid,true);
}
@@ -1128,7 +1131,6 @@ class Admin extends \Zotlabs\Web\Controller {
case "delete":{
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
// delete channel
require_once("include/Contact.php");
channel_remove($uid,true);
notice( sprintf(t("Channel '%s' deleted"), $channel[0]['channel_name']) . EOL);
@@ -1141,7 +1143,7 @@ class Admin extends \Zotlabs\Web\Controller {
intval($pflags),
intval( $uid )
);
proc_run('php','include/directory.php',$uid,'nopush');
\Zotlabs\Daemon\Master::Summon(array('Directory',$uid,'nopush'));
notice( sprintf( (($pflags & PAGE_CENSORED) ? t("Channel '%s' censored"): t("Channel '%s' uncensored")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL);
}; break;
@@ -1162,6 +1164,17 @@ class Admin extends \Zotlabs\Web\Controller {
}
goaway(z_root() . '/admin/channels' );
}
$key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'channel_id');
$dir = 'asc';
if(array_key_exists('dir',$_REQUEST))
$dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc');
$base = z_root() . '/admin/channels?f=';
$odir = (($dir === 'asc') ? '0' : '1');
/* get channels */
@@ -1170,14 +1183,12 @@ class Admin extends \Zotlabs\Web\Controller {
\App::set_pager_total($total[0]['total']);
\App::set_pager_itemspage(100);
}
$order = " order by channel_name asc ";
$channels = q("SELECT * from channel where channel_removed = 0 and channel_system = 0 $order limit %d offset %d ",
$channels = q("SELECT * from channel where channel_removed = 0 and channel_system = 0 order by $key $dir limit %d offset %d ",
intval(\App::$pager['itemspage']),
intval(\App::$pager['start'])
);
if($channels) {
for($x = 0; $x < count($channels); $x ++) {
if($channels[$x]['channel_pageflags'] & PAGE_CENSORED)
@@ -1205,7 +1216,12 @@ class Admin extends \Zotlabs\Web\Controller {
'$code' => t('Allow Code'),
'$uncode' => t('Disallow Code'),
'$h_channels' => t('Channel'),
'$th_channels' => array( t('UID'), t('Name'), t('Address')),
'$base' => $base,
'$odir' => $odir,
'$th_channels' => array(
[ t('UID'), 'channel_id' ],
[ t('Name'), 'channel_name' ],
[ t('Address'), 'channel_address' ]),
'$confirm_delete_multi' => t('Selected channels will be deleted!\n\nEverything that was posted in these channels on this site will be permanently deleted!\n\nAre you sure?'),
'$confirm_delete' => t('The channel {0} will be deleted!\n\nEverything that was posted in this channel on this site will be permanently deleted!\n\nAre you sure?'),
@@ -1295,7 +1311,7 @@ class Admin extends \Zotlabs\Web\Controller {
$admin_form = '';
$r = q("select * from addon where plugin_admin = 1 and name = '%s' limit 1",
$r = q("select * from addon where plugin_admin = 1 and aname = '%s' limit 1",
dbesc($plugin)
);
@@ -1408,7 +1424,9 @@ class Admin extends \Zotlabs\Web\Controller {
'$plugins' => $plugins,
'$disabled' => t('Disabled - version incompatibility'),
'$form_security_token' => get_form_security_token('admin_plugins'),
'$addrepo' => t('Add Plugin Repo'),
'$managerepos' => t('Manage Repos'),
'$installedtitle' => t('Installed Plugin Repositories'),
'$addnewrepotitle' => t('Install a New Plugin Repository'),
'$expandform' => false,
'$form' => $admin_plugins_add_repo_form,
'$newRepoModal' => $newRepoModal,
@@ -1423,13 +1441,15 @@ class Admin extends \Zotlabs\Web\Controller {
function listAddonRepos() {
$addonrepos = [];
$addonDir = __DIR__ . '/../../extend/addon/';
if ($handle = opendir($addonDir)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
$addonrepos[] = $entry;
if(is_dir($addonDir)) {
if ($handle = opendir($addonDir)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
$addonrepos[] = $entry;
}
}
closedir($handle);
}
closedir($handle);
}
return $addonrepos;
}
@@ -1547,8 +1567,8 @@ class Admin extends \Zotlabs\Web\Controller {
// Toggle theme status
toggle_theme($themes, $theme, $result);
$s = rebuild_theme_table($themes);
$this->toggle_theme($themes, $theme, $result);
$s = $this->rebuild_theme_table($themes);
if($result)
info( sprintf('Theme %s enabled.', $theme));
else
@@ -1561,7 +1581,7 @@ class Admin extends \Zotlabs\Web\Controller {
// display theme details
require_once('library/markdown.php');
if (theme_status($themes,$theme)) {
if ($this->theme_status($themes,$theme)) {
$status="on"; $action= t("Disable");
} else {
$status="off"; $action= t("Enable");
@@ -1718,7 +1738,7 @@ class Admin extends \Zotlabs\Web\Controller {
// name, label, value, help string, extra data...
'$debugging' => array('debugging', t("Debugging"),get_config('system','debugging'), ""),
'$logfile' => array('logfile', t("Log file"), get_config('system','logfile'), t("Must be writable by web server. Relative to your Red top-level directory.")),
'$logfile' => array('logfile', t("Log file"), get_config('system','logfile'), t("Must be writable by web server. Relative to your top-level webserver directory.")),
'$loglevel' => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices),
'$form_security_token' => get_form_security_token('admin_logs'),
@@ -1733,7 +1753,20 @@ class Admin extends \Zotlabs\Web\Controller {
} else {
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
}
$repoDir = __DIR__ . '/../../store/git/sys/extend/addon/' . $repoName;
$extendDir = __DIR__ . '/../../store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
if (!file_exists($extendDir)) {
if (!mkdir($extendDir, 0770, true)) {
logger('Error creating extend folder: ' . $extendDir);
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
} else {
if (!symlink(__DIR__ . '/../../extend/addon', $addonDir)) {
logger('Error creating symlink to addon folder: ' . $addonDir);
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
}
}
}
$repoDir = __DIR__ . '/../../store/[data]/git/sys/extend/addon/' . $repoName;
if (!is_dir($repoDir)) {
logger('Repo directory does not exist: ' . $repoDir);
json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
@@ -1745,6 +1778,18 @@ class Admin extends \Zotlabs\Web\Controller {
$git = new GitRepo('sys', null, false, $repoName, $repoDir);
try {
if ($git->pull()) {
$files = array_diff(scandir($repoDir), array('.', '..'));
foreach ($files as $file) {
if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
$source = '../extend/addon/' . $repoName . '/' . $file;
$target = realpath(__DIR__ . '/../../addon/') . '/' . $file;
unlink($target);
if (!symlink($source, $target)) {
logger('Error linking addons to /addon');
json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
}
}
}
json_return_and_die(array('message' => 'Repo updated.', 'success' => true));
} else {
json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
@@ -1758,7 +1803,20 @@ class Admin extends \Zotlabs\Web\Controller {
} else {
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
}
$repoDir = __DIR__ . '/../../store/git/sys/extend/addon/' . $repoName;
$extendDir = __DIR__ . '/../../store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
if (!file_exists($extendDir)) {
if (!mkdir($extendDir, 0770, true)) {
logger('Error creating extend folder: ' . $extendDir);
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
} else {
if (!symlink(__DIR__ . '/../../extend/addon', $addonDir)) {
logger('Error creating symlink to addon folder: ' . $addonDir);
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
}
}
}
$repoDir = __DIR__ . '/../../store/[data]/git/sys/extend/addon/' . $repoName;
if (!is_dir($repoDir)) {
logger('Repo directory does not exist: ' . $repoDir);
json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
@@ -1778,7 +1836,7 @@ class Admin extends \Zotlabs\Web\Controller {
if (array_key_exists('repoURL', $_REQUEST)) {
require __DIR__ . '/../../library/PHPGit.autoload.php'; // Load PHPGit dependencies
$repoURL = $_REQUEST['repoURL'];
$extendDir = __DIR__ . '/../../store/git/sys/extend';
$extendDir = __DIR__ . '/../../store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
if (!file_exists($extendDir)) {
if (!mkdir($extendDir, 0770, true)) {
@@ -1806,7 +1864,7 @@ class Admin extends \Zotlabs\Web\Controller {
json_return_and_die(array('message' => 'Invalid git repo', 'success' => false));
}
$repoDir = $addonDir . '/' . $repoName;
$tempRepoBaseDir = __DIR__ . '/../../store/git/sys/temp/';
$tempRepoBaseDir = __DIR__ . '/../../store/[data]/git/sys/temp/';
$tempAddonDir = $tempRepoBaseDir . $repoName;
if (!is_writable($addonDir) || !is_writable($tempAddonDir)) {
@@ -1840,9 +1898,9 @@ class Admin extends \Zotlabs\Web\Controller {
if (array_key_exists('repoURL', $_REQUEST)) {
require __DIR__ . '/../../library/PHPGit.autoload.php'; // Load PHPGit dependencies
$repoURL = $_REQUEST['repoURL'];
$extendDir = __DIR__ . '/../../store/git/sys/extend';
$extendDir = __DIR__ . '/../../store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
$tempAddonDir = __DIR__ . '/../../store/git/sys/temp';
$tempAddonDir = __DIR__ . '/../../store/[data]/git/sys/temp';
if (!file_exists($extendDir)) {
if (!mkdir($extendDir, 0770, true)) {
logger('Error creating extend folder: ' . $extendDir);
@@ -1854,6 +1912,12 @@ class Admin extends \Zotlabs\Web\Controller {
}
}
}
if (!is_dir($tempAddonDir)) {
if (!mkdir($tempAddonDir, 0770, true)) {
logger('Error creating temp plugin repo folder: ' . $tempAddonDir);
json_return_and_die(array('message' => 'Error creating temp plugin repo folder: ' . $tempAddonDir, 'success' => false));
}
}
$repoName = null;
if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
$repoName = $_REQUEST['repoName'];

View File

@@ -107,7 +107,7 @@ class Api extends \Zotlabs\Web\Controller {
$r = q("SELECT `clients`.*
FROM `clients`, `tokens`
WHERE `clients`.`client_id`=`tokens`.`client_id`
AND `tokens`.`id`='%s' AND `tokens`.`scope`='request'",
AND `tokens`.`id`='%s' AND `tokens`.`auth_scope`='request'",
dbesc($token));
if (!count($r))

View File

@@ -2,8 +2,9 @@
namespace Zotlabs\Module;
require_once('include/apps.php');
//require_once('include/apps.php');
use \Zotlabs\Lib as Zlib;
class Appman extends \Zotlabs\Web\Controller {
@@ -30,16 +31,16 @@ class Appman extends \Zotlabs\Web\Controller {
'categories' => escape_tags($_REQUEST['categories'])
);
$_REQUEST['appid'] = app_install(local_channel(),$arr);
$_REQUEST['appid'] = Zlib\Apps::app_install(local_channel(),$arr);
if(app_installed(local_channel(),$arr))
if(Zlib\Apps::app_installed(local_channel(),$arr))
info( t('App installed.') . EOL);
return;
}
$papp = app_decode($_POST['papp']);
$papp = Zlib\Apps::app_decode($_POST['papp']);
if(! is_array($papp)) {
notice( t('Malformed app.') . EOL);
@@ -47,13 +48,13 @@ class Appman extends \Zotlabs\Web\Controller {
}
if($_POST['install']) {
app_install(local_channel(),$papp);
if(app_installed(local_channel(),$papp))
Zlib\Apps::app_install(local_channel(),$papp);
if(Zlib\Apps::app_installed(local_channel(),$papp))
info( t('App installed.') . EOL);
}
if($_POST['delete']) {
app_destroy(local_channel(),$papp);
Zlib\Apps::app_destroy(local_channel(),$papp);
}
if($_POST['edit']) {
@@ -100,7 +101,7 @@ class Appman extends \Zotlabs\Web\Controller {
}
}
$embed = array('embed', t('Embed code'), app_encode($app,true),'', 'onclick="this.select();"');
$embed = array('embed', t('Embed code'), Zlib\Apps::app_encode($app,true),'', 'onclick="this.select();"');
}

View File

@@ -1,8 +1,9 @@
<?php
namespace Zotlabs\Module;
require_once('include/apps.php');
//require_once('include/apps.php');
use \Zotlabs\Lib as Zlib;
class Apps extends \Zotlabs\Web\Controller {
@@ -19,25 +20,25 @@ class Apps extends \Zotlabs\Web\Controller {
if(local_channel()) {
import_system_apps();
Zlib\Apps::import_system_apps();
$syslist = array();
$list = app_list(local_channel(), false, $_GET['cat']);
$list = Zlib\Apps::app_list(local_channel(), false, $_GET['cat']);
if($list) {
foreach($list as $x) {
$syslist[] = app_encode($x);
$syslist[] = Zlib\Apps::app_encode($x);
}
}
translate_system_apps($syslist);
Zlib\Apps::translate_system_apps($syslist);
}
else
$syslist = get_system_apps(true);
$syslist = Zlib\Apps::get_system_apps(true);
usort($syslist,'app_name_compare');
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
// logger('apps: ' . print_r($syslist,true));
foreach($syslist as $app) {
$apps[] = app_render($app,$mode);
$apps[] = Zlib\Apps::app_render($app,$mode);
}
return replace_macros(get_markup_template('myapps.tpl'), array(

View File

@@ -40,7 +40,7 @@ class Attach extends \Zotlabs\Web\Controller {
header('Content-disposition: attachment; filename="' . $r['data']['filename'] . '"');
if(intval($r['data']['os_storage'])) {
$fname = dbunescbin($r['data']['data']);
$fname = dbunescbin($r['data']['content']);
if(strpos($fname,'store') !== false)
$istream = fopen($fname,'rb');
else
@@ -53,7 +53,7 @@ class Attach extends \Zotlabs\Web\Controller {
}
}
else
echo dbunescbin($r['data']['data']);
echo dbunescbin($r['data']['content']);
killme();
}

View File

@@ -12,7 +12,7 @@ class Block extends \Zotlabs\Web\Controller {
$which = argv(1);
$profile = 0;
profile_load($a,$which,$profile);
profile_load($which,$profile);
if(\App::$profile['profile_uid'])
head_set_icon(\App::$profile['thumb']);
@@ -52,8 +52,8 @@ class Block extends \Zotlabs\Web\Controller {
require_once('include/security.php');
$sql_options = item_permissions_sql($u[0]['channel_id']);
$r = q("select item.* from item left join item_id on item.id = item_id.iid
where item.uid = %d and sid = '%s' and service = 'BUILDBLOCK' and
$r = q("select item.* from item left join iconfig on item.id = iconfig.iid
where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s' and iconfig.k = 'BUILDBLOCK' and
item_type = %d $sql_options $revision limit 1",
intval($u[0]['channel_id']),
dbesc($page_id),
@@ -64,8 +64,8 @@ class Block extends \Zotlabs\Web\Controller {
// Check again with no permissions clause to see if it is a permissions issue
$x = q("select item.* from item left join item_id on item.id = item_id.iid
where item.uid = %d and sid = '%s' and service = 'BUILDBLOCK' and
$x = q("select item.* from item left join iconfig on item.id = iconfig.iid
where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s' and iconfig.k = 'BUILDBLOCK' and
item_type = %d $revision limit 1",
intval($u[0]['channel_id']),
dbesc($page_id),

View File

@@ -1,7 +1,7 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/channel.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
@@ -22,12 +22,12 @@ class Blocks extends \Zotlabs\Web\Controller {
else
return;
profile_load($a,$which);
profile_load($which);
}
function get() {
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
@@ -111,8 +111,11 @@ class Blocks extends \Zotlabs\Web\Controller {
$editor = status_editor($a,$x);
$r = q("select iid, sid, mid, title, body, mimetype, created, edited from item_id left join item on item_id.iid = item.id
where item_id.uid = %d and service = 'BUILDBLOCK' and item_type = %d order by item.created desc",
$r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig
left join item on iconfig.iid = item.id
where uid = %d and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'
and item_type = %d order by item.created desc",
intval($owner),
intval(ITEM_TYPE_BLOCK)
);
@@ -129,12 +132,12 @@ class Blocks extends \Zotlabs\Web\Controller {
'created' => $rr['created'],
'edited' => $rr['edited'],
'mimetype' => $rr['mimetype'],
'pagetitle' => $rr['sid'],
'pagetitle' => $rr['v'],
'mid' => $rr['mid']
);
$pages[$rr['iid']][] = array(
'url' => $rr['iid'],
'name' => $rr['sid'],
'name' => $rr['v'],
'title' => $rr['title'],
'created' => $rr['created'],
'edited' => $rr['edited'],

View File

@@ -6,14 +6,12 @@ require_once('include/bbcode.php');
require_once('include/datetime.php');
require_once('include/event.php');
require_once('include/items.php');
require_once('include/Contact.php');
class Cal extends \Zotlabs\Web\Controller {
function init() {
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
if(observer_prohibited()) {
return;
}
@@ -22,7 +20,7 @@ class Cal extends \Zotlabs\Web\Controller {
if(argc() > 1) {
$nick = argv(1);
profile_load($a,$nick);
profile_load($nick);
$channelx = channelx_by_nick($nick);
@@ -47,13 +45,12 @@ class Cal extends \Zotlabs\Web\Controller {
function get() {
function get() {
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
if(observer_prohibited()) {
return;
}
$channel = null;
if(argc() > 1) {
@@ -94,7 +91,7 @@ class Cal extends \Zotlabs\Web\Controller {
$mode = 'view';
$y = 0;
$m = 0;
$ignored = ((x($_REQUEST,'ignored')) ? " and ignored = " . intval($_REQUEST['ignored']) . " " : '');
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
// logger('args: ' . print_r(\App::$argv,true));
@@ -149,7 +146,7 @@ class Cal extends \Zotlabs\Web\Controller {
$ftext = datetime_convert('UTC',$tz,$fdt);
$ftext = substr($ftext,0,14) . "00:00";
$type = ((x($orig_event)) ? $orig_event['type'] : 'event');
$type = ((x($orig_event)) ? $orig_event['etype'] : 'event');
$f = get_config('system','event_input_format');
if(! $f)
@@ -160,7 +157,7 @@ class Cal extends \Zotlabs\Web\Controller {
$show_bd = perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts');
if(! $show_bd) {
$sql_extra .= " and event.type != 'birthday' ";
$sql_extra .= " and event.etype != 'birthday' ";
}
@@ -228,8 +225,8 @@ class Cal extends \Zotlabs\Web\Controller {
$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 $ignored
AND (( adjust = 0 AND ( finish >= '%s' or nofinish = 1 ) AND start <= '%s' )
OR ( adjust = 1 AND ( finish >= '%s' or nofinish = 1 ) AND start <= '%s' )) $sql_extra ",
AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )
OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) $sql_extra ",
intval($channel['channel_id']),
dbesc($start),
dbesc($finish),
@@ -250,7 +247,7 @@ class Cal extends \Zotlabs\Web\Controller {
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j'));
$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;
}
@@ -265,15 +262,15 @@ class Cal extends \Zotlabs\Web\Controller {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j'));
$d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], $fmt) : datetime_convert('UTC','UTC',$rr['start'],$fmt));
$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['start'], 'c') : datetime_convert('UTC','UTC',$rr['start'],'c'));
$start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'c') : datetime_convert('UTC','UTC',$rr['dtstart'],'c'));
if ($rr['nofinish']){
$end = null;
} else {
$end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['finish'], 'c') : datetime_convert('UTC','UTC',$rr['finish'],'c'));
$end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c'));
}

View File

@@ -9,357 +9,359 @@ require_once('include/security.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/permissions.php');
require_once('include/PermissionDescription.php');
class Channel extends \Zotlabs\Web\Controller {
function init() {
function init() {
$which = null;
if(argc() > 1)
$which = argv(1);
if(! $which) {
if(local_channel()) {
$channel = \App::get_channel();
if($channel && $channel['channel_address'])
$which = null;
if(argc() > 1)
$which = argv(1);
if(! $which) {
if(local_channel()) {
$channel = \App::get_channel();
if($channel && $channel['channel_address'])
$which = $channel['channel_address'];
}
}
if(! $which) {
notice( t('You must be logged in to see this page.') . EOL );
return;
}
$profile = 0;
$channel = \App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
}
}
if(! $which) {
notice( t('You must be logged in to see this page.') . EOL );
return;
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" title="' . t('Posts and comments') . '" href="' . z_root() . '/feed/' . $which . '" />' . "\r\n" ;
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" title="' . t('Only posts') . '" href="' . z_root() . '/feed/' . $which . '?top=1" />' . "\r\n" ;
// Not yet ready for prime time
// \App::$page['htmlhead'] .= '<link rel="openid.server" href="' . z_root() . '/id/' . $which .'?f=" />' . "\r\n" ;
// \App::$page['htmlhead'] .= '<link rel="openid.delegate" href="' . z_root() . '/channel/' . $which .'" />' . "\r\n" ;
// Run profile_load() here to make sure the theme is set before
// we start loading content
profile_load($which,$profile);
}
$profile = 0;
$channel = \App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
}
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" title="' . t('Posts and comments') . '" href="' . z_root() . '/feed/' . $which . '" />' . "\r\n" ;
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" title="' . t('Only posts') . '" href="' . z_root() . '/feed/' . $which . '?top=1" />' . "\r\n" ;
// Not yet ready for prime time
// \App::$page['htmlhead'] .= '<link rel="openid.server" href="' . z_root() . '/id/' . $which .'?f=" />' . "\r\n" ;
// \App::$page['htmlhead'] .= '<link rel="openid.delegate" href="' . z_root() . '/channel/' . $which .'" />' . "\r\n" ;
// Run profile_load() here to make sure the theme is set before
// we start loading content
profile_load($a,$which,$profile);
}
function get($update = 0, $load = false) {
function get($update = 0, $load = false) {
if($load)
$_SESSION['loadtime'] = datetime_convert();
if($load)
$_SESSION['loadtime'] = datetime_convert();
$checkjs = new \Zotlabs\Web\CheckJS(1);
$checkjs = new \Zotlabs\Web\CheckJS(1);
$category = $datequery = $datequery2 = '';
$category = $datequery = $datequery2 = '';
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
if(get_config('system','block_public') && (! get_account_id()) && (! remote_channel())) {
if(observer_prohibited(true)) {
return login();
}
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
$groups = array();
$o = '';
if($update) {
// Ensure we've got a profile owner if updating.
\App::$profile['profile_uid'] = \App::$profile_uid = $update;
}
else {
if(\App::$profile['profile_uid'] == local_channel()) {
nav_set_selected('home');
}
}
$is_owner = (((local_channel()) && (\App::$profile['profile_uid'] == local_channel())) ? true : false);
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
$channel = \App::get_channel();
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$groups = array();
$perms = get_all_perms(\App::$profile['profile_uid'],$ob_hash);
$o = '';
if(! $perms['view_stream']) {
if($update) {
// Ensure we've got a profile owner if updating.
\App::$profile['profile_uid'] = \App::$profile_uid = $update;
}
else {
if(\App::$profile['profile_uid'] == local_channel()) {
nav_set_selected('home');
}
}
$is_owner = (((local_channel()) && (\App::$profile['profile_uid'] == local_channel())) ? true : false);
$channel = \App::get_channel();
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms(\App::$profile['profile_uid'],$ob_hash);
if(! $perms['view_stream']) {
// We may want to make the target of this redirect configurable
if($perms['view_profile']) {
notice( t('Insufficient permissions. Request redirected to profile page.') . EOL);
goaway (z_root() . "/profile/" . \App::$profile['channel_address']);
}
notice( t('Permission denied.') . EOL);
return;
}
if(! $update) {
$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
$o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
if($channel && $is_owner) {
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
notice( t('Permission denied.') . EOL);
return;
}
if(! $update) {
$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
$o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
if($channel && $is_owner) {
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
}
else
$channel_acl = array();
if($perms['post_wall']) {
$x = array(
'is_owner' => $is_owner,
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(\App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
'default_location' => (($is_owner) ? \App::$profile['channel_location'] : ''),
'nickname' => \App::$profile['channel_address'],
'lockstate' => (((strlen(\App::$profile['channel_allow_cid'])) || (strlen(\App::$profile['channel_allow_gid'])) || (strlen(\App::$profile['channel_deny_cid'])) || (strlen(\App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
'permissions' => (($is_owner) ? $channel_acl : ''),
'showacl' => (($is_owner) ? 'yes' : ''),
'bang' => '',
'visitor' => (($is_owner || $observer) ? true : false),
'profile_uid' => \App::$profile['profile_uid'],
'editor_autocomplete' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
$o .= status_editor($a,$x);
}
}
/**
* Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
*/
$item_normal = item_normal();
$sql_extra = item_permissions_sql(\App::$profile['profile_uid']);
if(get_pconfig(\App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid))
$page_mode = 'list';
else
$channel_acl = array();
$page_mode = 'client';
$abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " ";
if($perms['post_wall']) {
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
$x = array(
'is_owner' => $is_owner,
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(\App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
'default_location' => (($is_owner) ? \App::$profile['channel_location'] : ''),
'nickname' => \App::$profile['channel_address'],
'lockstate' => (((strlen(\App::$profile['channel_allow_cid'])) || (strlen(\App::$profile['channel_allow_gid'])) || (strlen(\App::$profile['channel_deny_cid'])) || (strlen(\App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl,true, \PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
'showacl' => (($is_owner) ? 'yes' : ''),
'bang' => '',
'visitor' => (($is_owner || $observer) ? true : false),
'profile_uid' => \App::$profile['profile_uid'],
'editor_autocomplete' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
$o .= status_editor($a,$x);
}
}
/**
* Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
*/
$item_normal = item_normal();
$sql_extra = item_permissions_sql(\App::$profile['profile_uid']);
if(get_pconfig(\App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid))
$page_mode = 'list';
else
$page_mode = 'client';
$abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " ";
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
\App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string) . '" title="oembed" />' . "\r\n";
\App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string) . '" title="oembed" />' . "\r\n";
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
if($load)
$simple_update = '';
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
if($load)
$simple_update = '';
if(($update) && (! $load)) {
if(($update) && (! $load)) {
if ($mid) {
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
AND item_wall = 1 AND item_unseen = 1 $sql_extra limit 1",
dbesc($mid . '%'),
intval(\App::$profile['profile_uid'])
);
} else {
$r = q("SELECT distinct parent AS `item_id`, created from item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
WHERE uid = %d $item_normal
AND item_wall = 1 $simple_update
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra
ORDER BY created DESC",
intval(\App::$profile['profile_uid'])
);
$_SESSION['loadtime'] = datetime_convert();
}
}
else {
if(x($category)) {
$sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY));
}
if(x($hashtags)) {
$sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
}
if($datequery) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
}
if($datequery2) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
$itemspage = get_pconfig(local_channel(),'system','itemspage');
\App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
if($load || ($checkjs->disabled())) {
if ($mid) {
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal
AND item_wall = 1 $sql_extra limit 1",
dbesc($mid),
if($mid) {
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
AND item_wall = 1 AND item_unseen = 1 $sql_extra limit 1",
dbesc($mid . '%'),
intval(\App::$profile['profile_uid'])
);
if (! $r) {
notice( t('Permission denied.') . EOL);
}
} else {
$r = q("SELECT distinct id AS item_id, created FROM item
left join abook on item.author_xchan = abook.abook_xchan
}
else {
$r = q("SELECT distinct parent AS `item_id`, created from item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
WHERE uid = %d $item_normal
AND item_wall = 1 and item_thread_top = 1
AND (abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $sql_extra2
ORDER BY created DESC $pager_sql ",
AND item_wall = 1 $simple_update
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra
ORDER BY created DESC",
intval(\App::$profile['profile_uid'])
);
$_SESSION['loadtime'] = datetime_convert();
}
}
else {
if(x($category)) {
$sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY));
}
if(x($hashtags)) {
$sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
}
if($datequery) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
}
if($datequery2) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
$itemspage = get_pconfig(local_channel(),'system','itemspage');
\App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
if($load || ($checkjs->disabled())) {
if($mid) {
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal
AND item_wall = 1 $sql_extra limit 1",
dbesc($mid),
intval(\App::$profile['profile_uid'])
);
if (! $r) {
notice( t('Permission denied.') . EOL);
}
}
else {
$r = q("SELECT distinct id AS item_id, created FROM item
left join abook on item.author_xchan = abook.abook_xchan
WHERE uid = %d $item_normal
AND item_wall = 1 and item_thread_top = 1
AND (abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $sql_extra2
ORDER BY created DESC $pager_sql ",
intval(\App::$profile['profile_uid'])
);
}
}
else {
$r = array();
}
}
if($r) {
$parents_str = ids_to_querystr($r,'item_id');
$items = q("SELECT `item`.*, `item`.`id` AS `item_id`
FROM `item`
WHERE `item`.`uid` = %d $item_normal
AND `item`.`parent` IN ( %s )
$sql_extra ",
intval(\App::$profile['profile_uid']),
dbesc($parents_str)
);
xchan_query($items);
$items = fetch_post_tags($items, true);
$items = conv_sort($items,'created');
if($load && $mid && (! count($items))) {
// This will happen if we don't have sufficient permissions
// to view the parent item (or the item itself if it is toplevel)
notice( t('Permission denied.') . EOL);
}
}
else {
$items = array();
}
if((! $update) && (! $load)) {
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.
$maxheight = get_pconfig(\App::$profile['profile_uid'],'system','channel_divmore_height');
if(! $maxheight)
$maxheight = 400;
$o .= '<div id="live-channel"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . \App::$profile['profile_uid']
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'channel',
'$uid' => ((\App::$profile['profile_uid']) ? \App::$profile['profile_uid'] : '0'),
'$gid' => '0',
'$cid' => '0',
'$cmin' => '0',
'$cmax' => '0',
'$star' => '0',
'$liked' => '0',
'$conv' => '0',
'$spam' => '0',
'$nouveau' => '0',
'$wall' => '1',
'$fh' => '0',
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => '',
'$order' => '',
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$file' => '',
'$cats' => (($category) ? $category : ''),
'$tags' => (($hashtags) ? $hashtags : ''),
'$mid' => $mid,
'$verb' => '',
'$dend' => $datequery,
'$dbegin' => $datequery2
));
}
$update_unseen = '';
if($page_mode === 'list') {
/**
* in "list mode", only mark the parent item and any like activities as "seen".
* We won't distinguish between comment likes and post likes. The important thing
* is that the number of unseen comments will be accurate. The SQL to separate the
* comment likes could also get somewhat hairy.
*/
if($parents_str) {
$update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )";
$update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) ";
}
}
else {
$r = array();
}
}
if($r) {
$parents_str = ids_to_querystr($r,'item_id');
$items = q("SELECT `item`.*, `item`.`id` AS `item_id`
FROM `item`
WHERE `item`.`uid` = %d $item_normal
AND `item`.`parent` IN ( %s )
$sql_extra ",
intval(\App::$profile['profile_uid']),
dbesc($parents_str)
);
xchan_query($items);
$items = fetch_post_tags($items, true);
$items = conv_sort($items,'created');
if ($load && $mid && (! count($items))) {
// This will happen if we don't have sufficient permissions
// to view the parent item (or the item itself if it is toplevel)
notice( t('Permission denied.') . EOL);
if($parents_str) {
$update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )";
}
}
} else {
$items = array();
}
if((! $update) && (! $load)) {
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.
$maxheight = get_pconfig(\App::$profile['profile_uid'],'system','channel_divmore_height');
if(! $maxheight)
$maxheight = 400;
$o .= '<div id="live-channel"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . \App::$profile['profile_uid']
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'channel',
'$uid' => ((\App::$profile['profile_uid']) ? \App::$profile['profile_uid'] : '0'),
'$gid' => '0',
'$cid' => '0',
'$cmin' => '0',
'$cmax' => '0',
'$star' => '0',
'$liked' => '0',
'$conv' => '0',
'$spam' => '0',
'$nouveau' => '0',
'$wall' => '1',
'$fh' => '0',
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => '',
'$order' => '',
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$file' => '',
'$cats' => (($category) ? $category : ''),
'$tags' => (($hashtags) ? $hashtags : ''),
'$mid' => $mid,
'$verb' => '',
'$dend' => $datequery,
'$dbegin' => $datequery2
));
}
$update_unseen = '';
if($page_mode === 'list') {
/**
* in "list mode", only mark the parent item and any like activities as "seen".
* We won't distinguish between comment likes and post likes. The important thing
* is that the number of unseen comments will be accurate. The SQL to separate the
* comment likes could also get somewhat hairy.
*/
if($parents_str) {
$update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )";
$update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) ";
if($is_owner && $update_unseen) {
$r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d $update_unseen",
intval(local_channel())
);
}
}
else {
if($parents_str) {
$update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )";
if($checkjs->disabled()) {
$o .= conversation($a,$items,'channel',$update,'traditional');
}
else {
$o .= conversation($a,$items,'channel',$update,$page_mode);
}
if((! $update) || ($checkjs->disabled())) {
$o .= alt_pager($a,count($items));
if ($mid && $items[0]['title'])
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
}
if($mid)
$o .= '<div id="content-complete"></div>';
return $o;
}
if($is_owner && $update_unseen) {
$r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d $update_unseen",
intval(local_channel())
);
}
if($checkjs->disabled()) {
$o .= conversation($a,$items,'channel',$update,'traditional');
} else {
$o .= conversation($a,$items,'channel',$update,$page_mode);
}
if((! $update) || ($checkjs->disabled())) {
$o .= alt_pager($a,count($items));
if ($mid && $items[0]['title'])
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
}
if($mid)
$o .= '<div id="content-complete"></div>';
return $o;
}
}

View File

@@ -1,10 +1,8 @@
<?php
namespace Zotlabs\Module;
require_once('include/Contact.php');
require_once('include/zot.php');
class Chanview extends \Zotlabs\Web\Controller {
function get() {
@@ -62,18 +60,15 @@ class Chanview extends \Zotlabs\Web\Controller {
}
if($_REQUEST['address']) {
$ret = zot_finger($_REQUEST['address'],null);
if($ret['success']) {
$j = json_decode($ret['body'],true);
if($j)
import_xchan($j);
$j = \Zotlabs\Zot\Finger::run($_REQUEST['address'],null);
if($j['success']) {
import_xchan($j);
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
dbesc($_REQUEST['address'])
);
if($r)
\App::$poi = $r[0];
}
}
}

View File

@@ -1,9 +1,11 @@
<?php
namespace Zotlabs\Module; /** @file */
<?php /** @file */
namespace Zotlabs\Module;
require_once('include/chat.php');
require_once('include/bookmarks.php');
use \Zotlabs\Lib as Zlib;
class Chat extends \Zotlabs\Web\Controller {
@@ -37,11 +39,11 @@ class Chat extends \Zotlabs\Web\Controller {
// Run profile_load() here to make sure the theme is set before
// we start loading content
profile_load($a,$which,$profile);
profile_load($which,$profile);
}
function post() {
function post() {
if($_POST['room_name'])
$room = strip_tags(trim($_POST['room_name']));
@@ -54,7 +56,7 @@ class Chat extends \Zotlabs\Web\Controller {
if($_POST['action'] === 'drop') {
logger('delete chatroom');
chatroom_destroy($channel,array('cr_name' => $room));
Zlib\Chatroom::destroy($channel,array('cr_name' => $room));
goaway(z_root() . '/chat/' . $channel['channel_address']);
}
@@ -67,7 +69,7 @@ class Chat extends \Zotlabs\Web\Controller {
if(intval($arr['expire']) < 0)
$arr['expire'] = 0;
chatroom_create($channel,$arr);
Zlib\Chatroom::create($channel,$arr);
$x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1",
dbesc($room),
@@ -87,7 +89,7 @@ class Chat extends \Zotlabs\Web\Controller {
}
function get() {
function get() {
if(local_channel())
$channel = \App::get_channel();
@@ -105,7 +107,7 @@ class Chat extends \Zotlabs\Web\Controller {
}
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'leave')) {
chatroom_leave($observer,argv(2),$_SERVER['REMOTE_ADDR']);
Zlib\Chatroom::leave($observer,argv(2),$_SERVER['REMOTE_ADDR']);
goaway(z_root() . '/channel/' . argv(1));
}
@@ -158,7 +160,7 @@ class Chat extends \Zotlabs\Web\Controller {
$room_id = intval(argv(2));
$bookmark_link = get_bookmark_link($ob);
$x = chatroom_enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']);
$x = Zlib\Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']);
if(! $x)
return;
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
@@ -216,14 +218,13 @@ class Chat extends \Zotlabs\Web\Controller {
notice( t('Feature disabled.') . EOL);
return $o;
}
$acl = new \Zotlabs\Access\AccessList($channel);
$channel_acl = $acl->get();
$lockstate = (($channel_acl['allow_cid'] || $channel_acl['allow_gid'] || $channel_acl['deny_cid'] || $channel_acl['deny_gid']) ? 'lock' : 'unlock');
require_once('include/acl_selectors.php');
$chatroom_new = '';
if(local_channel()) {
$chatroom_new = replace_macros(get_markup_template('chatroom_new.tpl'),array(
@@ -232,16 +233,20 @@ class Chat extends \Zotlabs\Web\Controller {
'$chat_expire' => array('chat_expire',t('Expiration of chats (minutes)'),120,''),
'$permissions' => t('Permissions'),
'$acl' => populate_acl($channel_acl,false),
'$allow_cid' => acl2json($channel_acl['allow_cid']),
'$allow_gid' => acl2json($channel_acl['allow_gid']),
'$deny_cid' => acl2json($channel_acl['deny_cid']),
'$deny_gid' => acl2json($channel_acl['deny_gid']),
'$lockstate' => $lockstate,
'$submit' => t('Submit')
));
}
$rooms = chatroom_list(\App::$profile['profile_uid']);
$rooms = Zlib\Chatroom::roomlist(\App::$profile['profile_uid']);
$o .= replace_macros(get_markup_template('chatrooms.tpl'), array(
'$header' => sprintf( t('%1$s\'s Chatrooms'), \App::$profile['name']),
'$header' => sprintf( t('%1$s\'s Chatrooms'), \App::$profile['fullname']),
'$name' => t('Name'),
'$baseurl' => z_root(),
'$nickname' => \App::$profile['channel_address'],

View File

@@ -1,14 +1,16 @@
<?php
namespace Zotlabs\Module; /** @file */
<?php /** @file */
namespace Zotlabs\Module;
require_once('include/security.php');
use \Zotlabs\Lib as Zlib;
class Chatsvc extends \Zotlabs\Web\Controller {
function init() {
//logger('chatsvc');
//logger('chatsvc');
$ret = array('success' => false);
@@ -27,7 +29,7 @@ class Chatsvc extends \Zotlabs\Web\Controller {
}
function post() {
function post() {
$ret = array('success' => false);
@@ -65,7 +67,7 @@ class Chatsvc extends \Zotlabs\Web\Controller {
json_return_and_die($ret);
}
function get() {
function get() {
$status = strip_tags($_REQUEST['status']);
$room_id = intval(\App::$data['chat']['room_id']);

View File

@@ -13,6 +13,9 @@ use \Zotlabs\Storage;
// composer autoloader for SabreDAV
require_once('vendor/autoload.php');
require_once('include/attach.php');
/**
* @brief Fires up the SabreDAV server.
*
@@ -23,7 +26,6 @@ require_once('vendor/autoload.php');
class Cloud extends \Zotlabs\Web\Controller {
function init() {
require_once('include/reddav.php');
if (! is_dir('store'))
os_mkdir('store', STORAGE_DEFAULT_PERMISSIONS, false);
@@ -37,7 +39,7 @@ class Cloud extends \Zotlabs\Web\Controller {
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $which . '" />' . "\r\n";
if ($which)
profile_load($a, $which, $profile);
profile_load( $which, $profile);
$auth = new \Zotlabs\Storage\BasicAuth();
@@ -79,17 +81,6 @@ class Cloud extends \Zotlabs\Web\Controller {
$is_readable = false;
if($_SERVER['REQUEST_METHOD'] === 'GET') {
try {
$x = RedFileData('/' . \App::$cmd, $auth);
}
catch(\Exception $e) {
if($e instanceof Sabre\DAV\Exception\Forbidden) {
http_status_exit(401, 'Permission denied.');
}
}
}
// provide a directory view for the cloud in Hubzilla
$browser = new \Zotlabs\Storage\Browser($auth);
$auth->setBrowserPlugin($browser);
@@ -100,9 +91,12 @@ class Cloud extends \Zotlabs\Web\Controller {
// require_once('\Zotlabs\Storage/QuotaPlugin.php');
// $server->addPlugin(new \Zotlabs\Storage\\QuotaPlugin($auth));
ob_start();
// All we need to do now, is to fire up the server
$server->exec();
ob_end_flush();
killme();
}

View File

@@ -21,7 +21,7 @@ class Common extends \Zotlabs\Web\Controller {
);
if($x)
profile_load($a,$x[0]['channel_address'],0);
profile_load($x[0]['channel_address'],0);
}

View File

@@ -2,7 +2,7 @@
namespace Zotlabs\Module; /** @file */
require_once('include/Contact.php');
require_once('include/contact_widgets.php');
require_once('include/items.php');
@@ -26,7 +26,7 @@ class Connect extends \Zotlabs\Web\Controller {
if($r)
\App::$data['channel'] = $r[0];
profile_load($a,$which,'');
profile_load($which,'');
}
function post() {
@@ -47,7 +47,8 @@ class Connect extends \Zotlabs\Web\Controller {
intval(PAGE_PREMIUM),
intval(local_channel())
);
proc_run('php','include/notifier.php','refresh_all',\App::$data['channel']['channel_id']);
\Zotlabs\Daemon\Master::Summon(array('Notifier','refresh_all',\App::$data['channel']['channel_id']));
}
set_pconfig(\App::$data['channel']['channel_id'],'system','selltext',$text);
// reload the page completely to get fresh data

View File

@@ -1,9 +1,9 @@
<?php
namespace Zotlabs\Module;
require_once('include/Contact.php');
require_once('include/socgraph.php');
require_once('include/contact_selectors.php');
require_once('include/selectors.php');
require_once('include/group.php');
require_once('include/contact_widgets.php');
require_once('include/zot.php');

View File

@@ -7,23 +7,23 @@ namespace Zotlabs\Module;
*
*/
require_once('include/Contact.php');
require_once('include/socgraph.php');
require_once('include/contact_selectors.php');
require_once('include/selectors.php');
require_once('include/group.php');
require_once('include/contact_widgets.php');
require_once('include/zot.php');
require_once('include/widgets.php');
require_once('include/photos.php');
/* @brief Initialize the connection-editor
*
*
*/
class Connedit extends \Zotlabs\Web\Controller {
/* @brief Initialize the connection-editor
*
*
*/
function init() {
if(! local_channel())
@@ -51,7 +51,7 @@ class Connedit extends \Zotlabs\Web\Controller {
*
*/
function post() {
function post() {
if(! local_channel())
return;
@@ -126,22 +126,42 @@ class Connedit extends \Zotlabs\Web\Controller {
$rating = 10;
$rating_text = trim(escape_tags($_REQUEST['rating_text']));
$abook_my_perms = 0;
foreach($_POST as $k => $v) {
if(strpos($k,'perms_') === 0) {
$abook_my_perms += $v;
$all_perms = \Zotlabs\Access\Permissions::Perms();
if($all_perms) {
foreach($all_perms as $perm => $desc) {
if(array_key_exists('perms_' . $perm, $_POST)) {
set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm,
intval($_POST['perms_' . $perm]));
if($autoperms) {
set_pconfig($channel['channel_id'],'autoperms',$perm,intval($_POST['perms_' . $perm]));
}
}
else {
set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm,0);
if($autoperms) {
set_pconfig($channel['channel_id'],'autoperms',$perm,0);
}
}
}
}
if(! is_null($autoperms))
set_pconfig($channel['channel_id'],'system','autoperms',$autoperms);
$new_friend = false;
// only store a record and notify the directory if the rating changed
if(! $is_self) {
$signed = $orig_record[0]['abook_xchan'] . '.' . $rating . '.' . $rating_text;
$sig = base64url_encode(rsa_sign($signed,$channel['channel_prvkey']));
$rated = ((intval($rating) || strlen($rating_text)) ? true : false);
$record = 0;
$z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
dbesc($channel['channel_hash']),
@@ -149,17 +169,20 @@ class Connedit extends \Zotlabs\Web\Controller {
);
if($z) {
$record = $z[0]['xlink_id'];
$w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s'
where xlink_id = %d",
intval($rating),
dbesc($rating_text),
dbesc($sig),
dbesc(datetime_convert()),
intval($record)
);
if(($z[0]['xlink_rating'] != $rating) || ($z[0]['xlink_rating_text'] != $rating_text)) {
$record = $z[0]['xlink_id'];
$w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s'
where xlink_id = %d",
intval($rating),
dbesc($rating_text),
dbesc($sig),
dbesc(datetime_convert()),
intval($record)
);
}
}
else {
elseif($rated) {
// only create a record if there's something to save
$w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ",
dbesc($channel['channel_hash']),
dbesc($orig_record[0]['abook_xchan']),
@@ -176,7 +199,7 @@ class Connedit extends \Zotlabs\Web\Controller {
$record = $z[0]['xlink_id'];
}
if($record) {
proc_run('php','include/ratenotif.php','rating',$record);
\Zotlabs\Daemon\Master::Summon(array('Ratenotif','rating',$record));
}
}
@@ -194,19 +217,25 @@ class Connedit extends \Zotlabs\Web\Controller {
$role = get_pconfig(local_channel(),'system','permissions_role');
if($role) {
$x = get_role_perms($role);
if($x['perms_accept'])
$abook_my_perms = $x['perms_accept'];
$x = \Zotlabs\Access\PermissionRoles::role_perms($role);
if($x['perms_connect']) {
$abook_my_perms = $x['perms_connect'];
}
}
$filled_perms = \Zotlabs\Access\Permissions::FilledPerms($abook_my_perms);
foreach($filled_perms as $k => $v) {
set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$k,$v);
}
}
$abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
$r = q("UPDATE abook SET abook_profile = '%s', abook_my_perms = %d , abook_closeness = %d, abook_pending = %d,
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
abook_incl = '%s', abook_excl = '%s'
where abook_id = %d AND abook_channel = %d",
dbesc($profile_id),
intval($abook_my_perms),
intval($closeness),
intval($abook_pending),
dbesc($abook_incl),
@@ -219,7 +248,7 @@ class Connedit extends \Zotlabs\Web\Controller {
//Update profile photo permissions
logger('A new profile was assigned - updating profile photos');
profile_photo_set_profile_perms($profile_id);
profile_photo_set_profile_perms(local_channel(),$profile_id);
}
@@ -227,10 +256,13 @@ class Connedit extends \Zotlabs\Web\Controller {
info( t('Connection updated.') . EOL);
else
notice( t('Failed to update connection record.') . EOL);
if(\App::$poi && \App::$poi['abook_my_perms'] != $abook_my_perms
&& (! intval(\App::$poi['abook_self']))) {
proc_run('php', 'include/notifier.php', (($new_friend) ? 'permission_create' : 'permission_update'), $contact_id);
if(! intval(\App::$poi['abook_self'])) {
\Zotlabs\Daemon\Master::Summon( [
'Notifier',
(($new_friend) ? 'permission_create' : 'permission_update'),
$contact_id
]);
}
if($new_friend) {
@@ -270,7 +302,7 @@ class Connedit extends \Zotlabs\Web\Controller {
array('rel' => 'photo', 'type' => \App::$poi['xchan_photo_mimetype'], 'href' => \App::$poi['xchan_photo_l'])
),
);
$xarr['object'] = json_encode($obj);
$xarr['obj'] = json_encode($obj);
$xarr['obj_type'] = ACTIVITY_OBJ_PERSON;
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . \App::$poi['xchan_url'] . ']' . \App::$poi['xchan_name'] . '[/zrl]';
@@ -283,7 +315,7 @@ class Connedit extends \Zotlabs\Web\Controller {
// pull in a bit of content if there is any to pull in
proc_run('php','include/onepoll.php',$contact_id);
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$contact_id));
}
@@ -304,9 +336,6 @@ class Connedit extends \Zotlabs\Web\Controller {
call_hooks('accept_follow', $arr);
}
if(! is_null($autoperms))
set_pconfig(local_channel(),'system','autoperms',(($autoperms) ? $abook_my_perms : 0));
$this->connedit_clone($a);
if(($_REQUEST['pending']) && (!$_REQUEST['done']))
@@ -345,7 +374,7 @@ class Connedit extends \Zotlabs\Web\Controller {
unset($clone['abook_account']);
unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_hash'],$clone['abook_xchan']);
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
if($abconfig)
$clone['abconfig'] = $abconfig;
@@ -357,7 +386,7 @@ class Connedit extends \Zotlabs\Web\Controller {
*
*/
function get() {
function get() {
$sort_type = 0;
$o = '';
@@ -371,9 +400,9 @@ class Connedit extends \Zotlabs\Web\Controller {
$my_perms = get_channel_default_perms(local_channel());
$role = get_pconfig(local_channel(),'system','permissions_role');
if($role) {
$x = get_role_perms($role);
if($x['perms_accept'])
$my_perms = $x['perms_accept'];
$x = \Zotlabs\Access\PermissionRoles::role_perms($role);
if($x['perms_connect'])
$my_perms = $x['perms_connect'];
}
$yes_no = array(t('No'),t('Yes'));
@@ -414,11 +443,17 @@ class Connedit extends \Zotlabs\Web\Controller {
if($cmd === 'update') {
// pull feed and consume it, which should subscribe to the hub.
proc_run('php',"include/poller.php","$contact_id");
\Zotlabs\Daemon\Master::Summon(array('Poller',$contact_id));
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'resetphoto') {
q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s' limit 1",
dbesc($orig_record[0]['xchan_hash'])
);
$cmd = 'refresh';
}
if($cmd === 'refresh') {
if($orig_record[0]['xchan_network'] === 'zot') {
if(! zot_refresh($orig_record[0],\App::get_channel()))
@@ -427,7 +462,7 @@ class Connedit extends \Zotlabs\Web\Controller {
else {
// if you are on a different network we'll force a refresh of the connection basic info
proc_run('php','include/notifier.php','permission_update',$contact_id);
\Zotlabs\Daemon\Master::Summon(array('Notifier','permission_update',$contact_id));
}
goaway(z_root() . '/connedit/' . $contact_id);
}
@@ -485,7 +520,6 @@ class Connedit extends \Zotlabs\Web\Controller {
if($cmd === 'drop') {
require_once('include/Contact.php');
// FIXME
// We need to send either a purge or a refresh packet to the other side (the channel being unfriended).
@@ -583,8 +617,6 @@ class Connedit extends \Zotlabs\Web\Controller {
if(intval($contact['abook_self']))
$self = true;
require_once('include/contact_selectors.php');
$tpl = get_markup_template("abook_edit.tpl");
if(feature_enabled(local_channel(),'affinity')) {
@@ -651,7 +683,8 @@ class Connedit extends \Zotlabs\Web\Controller {
$perms = array();
$channel = \App::get_channel();
$global_perms = get_perms();
$global_perms = \Zotlabs\Access\Permissions::Perms();
$existing = get_all_perms(local_channel(),$contact['abook_xchan']);
$unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'),('Yes')));
@@ -667,16 +700,32 @@ class Connedit extends \Zotlabs\Web\Controller {
if($slide && $multiprofs)
$affinity = t('Set Affinity & Profile');
$theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'",
intval(local_channel()),
dbesc($contact['abook_xchan'])
);
$their_perms = array();
if($theirs) {
foreach($theirs as $t) {
$their_perms[$t['k']] = $t['v'];
}
}
foreach($global_perms as $k => $v) {
$thisperm = (($contact['abook_my_perms'] & $v[1]) ? "1" : '');
$checkinherited = ((($channel[$v[0]]) && ($channel[$v[0]] != PERMS_SPECIFIC)) ? "1" : '');
$thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
//fixme
$checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
// For auto permissions (when $self is true) we don't want to look at existing
// permissions because they are enabled for the channel owner
if((! $self) && ($existing[$k]))
$thisperm = "1";
$perms[] = array('perms_' . $k, $v[3], (($contact['abook_their_perms'] & $v[1]) ? "1" : ""),$thisperm, $v[1], (($channel[$v[0]] == PERMS_SPECIFIC) ? '' : '1'), $v[4], $checkinherited);
$perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
}
$locstr = '';

View File

@@ -41,10 +41,10 @@ class Contactgroup extends \Zotlabs\Web\Controller {
if($change) {
if(in_array($change,$preselected)) {
group_rmv_member(local_channel(),$group['name'],$change);
group_rmv_member(local_channel(),$group['gname'],$change);
}
else {
group_add_member(local_channel(),$group['name'],$change);
group_add_member(local_channel(),$group['gname'],$change);
}
}
}

View File

@@ -8,7 +8,7 @@ namespace Zotlabs\Module;
*/
require_once('include/photo/photo_driver.php');
require_once('include/identity.php');
require_once('include/channel.php');
@@ -29,7 +29,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
}
$channel = \App::get_channel();
profile_load($a,$channel['channel_address']);
profile_load($channel['channel_address']);
}
@@ -40,7 +40,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
*
*/
function post() {
function post() {
if(! local_channel()) {
return;
@@ -50,7 +50,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
if((x($_POST,'cropfinal')) && ($_POST['cropfinal'] == 1)) {
if((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) {
// phase 2 - we have finished cropping
@@ -80,7 +80,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$profile = $r[0];
}
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND scale = 0 LIMIT 1",
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = 0 LIMIT 1",
dbesc($image_id),
intval(local_channel())
);
@@ -88,9 +88,9 @@ class Cover_photo extends \Zotlabs\Web\Controller {
if($r) {
$base_image = $r[0];
$base_image['data'] = (($r[0]['os_storage']) ? @file_get_contents($base_image['data']) : dbunescbin($base_image['data']));
$base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents($base_image['content']) : dbunescbin($base_image['content']));
$im = photo_factory($base_image['data'], $base_image['type']);
$im = photo_factory($base_image['content'], $base_image['mimetype']);
if($im->is_valid()) {
// We are scaling and cropping the relative pixel locations to the original photo instead of the
@@ -99,7 +99,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
// First load the scaled photo to check its size. (Should probably pass this in the post form and save
// a query.)
$g = q("select width, height from photo where resource_id = '%s' and uid = %d and scale = 3",
$g = q("select width, height from photo where resource_id = '%s' and uid = %d and imgscale = 3",
dbesc($image_id),
intval(local_channel())
);
@@ -133,26 +133,26 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$p = array('aid' => $aid, 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'],
'filename' => $base_image['filename'], 'album' => t('Cover Photos'));
$p['scale'] = 7;
$p['imgscale'] = 7;
$p['photo_usage'] = PHOTO_COVER;
$r1 = $im->save($p);
$im->doScaleImage(850,310);
$p['scale'] = 8;
$p['imgscale'] = 8;
$r2 = $im->save($p);
$im->doScaleImage(425,160);
$p['scale'] = 9;
$p['imgscale'] = 9;
$r3 = $im->save($p);
if($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over.
notice( t('Image resize failed.') . EOL );
$x = q("delete from photo where resource_id = '%s' and uid = %d and scale >= 7 ",
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale >= 7 ",
dbesc($base_image['resource_id']),
local_channel()
);
@@ -183,7 +183,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
logger('attach_store: ' . print_r($res,true));
if($res && intval($res['data']['is_photo'])) {
$i = q("select * from photo where resource_id = '%s' and uid = %d and scale = 0",
$i = q("select * from photo where resource_id = '%s' and uid = %d and imgscale = 0",
dbesc($hash),
intval(local_channel())
);
@@ -195,10 +195,10 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$os_storage = false;
foreach($i as $ii) {
$smallest = intval($ii['scale']);
$smallest = intval($ii['imgscale']);
$os_storage = intval($ii['os_storage']);
$imagedata = $ii['data'];
$filetype = $ii['type'];
$imagedata = $ii['content'];
$filetype = $ii['mimetype'];
}
}
@@ -224,10 +224,10 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
$arr['verb'] = ACTIVITY_UPDATE;
$arr['object'] = json_encode(array(
$arr['obj'] = json_encode(array(
'type' => $arr['obj_type'],
'id' => z_root() . '/photo/' . $photo['resource_id'] . '-7',
'link' => array('rel' => 'photo', 'type' => $photo['type'], 'href' => z_root() . '/photo/' . $photo['resource_id'] . '-7')
'link' => array('rel' => 'photo', 'type' => $photo['mimetype'], 'href' => z_root() . '/photo/' . $photo['resource_id'] . '-7')
));
if($profile && stripos($profile['gender'],t('female')) !== false)
@@ -271,7 +271,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
*/
function get() {
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL );
@@ -295,7 +295,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$resource_id = argv(2);
$r = q("SELECT id, album, scale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY scale ASC",
$r = q("SELECT id, album, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY imgscale ASC",
intval(local_channel()),
dbesc($resource_id)
);
@@ -305,11 +305,11 @@ class Cover_photo extends \Zotlabs\Web\Controller {
}
$havescale = false;
foreach($r as $rr) {
if($rr['scale'] == 7)
if($rr['imgscale'] == 7)
$havescale = true;
}
$r = q("SELECT `data`, `type`, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
$r = q("SELECT `content`, `mimetype`, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
intval($r[0]['id']),
intval(local_channel())
@@ -320,15 +320,15 @@ class Cover_photo extends \Zotlabs\Web\Controller {
}
if(intval($r[0]['os_storage']))
$data = @file_get_contents($r[0]['data']);
$data = @file_get_contents($r[0]['content']);
else
$data = dbunescbin($r[0]['data']);
$data = dbunescbin($r[0]['content']);
$ph = photo_factory($data, $r[0]['type']);
$ph = photo_factory($data, $r[0]['mimetype']);
$smallest = 0;
if($ph->is_valid()) {
// go ahead as if we have just uploaded a new photo to crop
$i = q("select resource_id, scale from photo where resource_id = '%s' and uid = %d and scale = 0",
$i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d and imgscale = 0",
dbesc($r[0]['resource_id']),
intval(local_channel())
);
@@ -336,12 +336,12 @@ class Cover_photo extends \Zotlabs\Web\Controller {
if($i) {
$hash = $i[0]['resource_id'];
foreach($i as $ii) {
$smallest = intval($ii['scale']);
$smallest = intval($ii['imgscale']);
}
}
}
cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
$this->cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
}

View File

@@ -14,6 +14,7 @@ use \Zotlabs\Storage;
// composer autoloader for SabreDAV
require_once('vendor/autoload.php');
require_once('include/attach.php');
/**
* @brief Fires up the SabreDAV server.
@@ -44,59 +45,16 @@ class Dav extends \Zotlabs\Web\Controller {
}
}
require_once('include/reddav.php');
if (! is_dir('store'))
os_mkdir('store', STORAGE_DEFAULT_PERMISSIONS, false);
$which = null;
if (argc() > 1)
$which = argv(1);
profile_load(argv(1),0);
$profile = 0;
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $which . '" />' . "\r\n";
if ($which)
profile_load($a, $which, $profile);
$auth = new \Zotlabs\Storage\BasicAuth();
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV');
// $authBackend = new \Sabre\DAV\Auth\Backend\BasicCallBack(function($userName,$password) {
// if(account_verify_password($userName,$password))
// return true;
// return false;
// });
// $ob_hash = get_observer_hash();
// if ($ob_hash) {
// if (local_channel()) {
// $channel = \App::get_channel();
// $auth->setCurrentUser($channel['channel_address']);
// $auth->channel_id = $channel['channel_id'];
// $auth->channel_hash = $channel['channel_hash'];
// $auth->channel_account_id = $channel['channel_account_id'];
// if($channel['channel_timezone'])
// $auth->setTimezone($channel['channel_timezone']);
// }
// $auth->observer = $ob_hash;
// }
// if ($_GET['davguest'])
// $_SESSION['davguest'] = true;
// $_SERVER['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['QUERY_STRING']);
// $_SERVER['QUERY_STRING'] = strip_zids($_SERVER['QUERY_STRING']);
// $_SERVER['QUERY_STRING'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['QUERY_STRING']);
//
// $_SERVER['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['REQUEST_URI']);
// $_SERVER['REQUEST_URI'] = strip_zids($_SERVER['REQUEST_URI']);
// $_SERVER['REQUEST_URI'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['REQUEST_URI']);
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
// A SabreDAV server-object
@@ -113,48 +71,13 @@ class Dav extends \Zotlabs\Web\Controller {
$server->addPlugin($lockPlugin);
// The next section of code allows us to bypass prompting for http-auth if a
// FILE is being accessed anonymously and permissions allow this. This way
// one can create hotlinks to public media files in their cloud and anonymous
// viewers won't get asked to login.
// If a DIRECTORY is accessed or there are permission issues accessing the
// file and we aren't previously authenticated via zot, prompt for HTTP-auth.
// This will be the default case for mounting a DAV directory.
// In order to avoid prompting for passwords for viewing a DIRECTORY, add
// the URL query parameter 'davguest=1'.
// $isapublic_file = false;
// $davguest = ((x($_SESSION, 'davguest')) ? true : false);
// if ((! $auth->observer) && ($_SERVER['REQUEST_METHOD'] === 'GET')) {
// try {
// $x = RedFileData('/' . \App::$cmd, $auth);
// if($x instanceof \Zotlabs\Storage\File)
// $isapublic_file = true;
// }
// catch (Exception $e) {
// $isapublic_file = false;
// }
// }
// if ((! $auth->observer) && (! $isapublic_file) && (! $davguest)) {
// try {
// $auth->Authenticate($server, t('$Projectname channel'));
// }
// catch (Exception $e) {
// logger('mod_cloud: auth exception' . $e->getMessage());
// http_status_exit($e->getHTTPCode(), $e->getMessage());
// }
// }
// require_once('Zotlabs/Storage/Browser.php');
// provide a directory view for the cloud in Hubzilla
$browser = new \Zotlabs\Storage\Browser($auth);
$auth->setBrowserPlugin($browser);
// Experimental QuotaPlugin
// require_once('Zotlabs/Storage/QuotaPlugin.php');
// $server->addPlugin(new \Zotlabs\Storage\QuotaPlugin($auth));
// require_once('Zotlabs/Storage/QuotaPlugin.php');
// $server->addPlugin(new \Zotlabs\Storage\QuotaPlugin($auth));
// All we need to do now, is to fire up the server
$server->exec();

View File

@@ -57,9 +57,9 @@ class Directory extends \Zotlabs\Web\Controller {
}
}
function get() {
function get() {
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
if(observer_prohibited()) {
notice( t('Public access denied.') . EOL);
return;
}

View File

@@ -7,17 +7,13 @@ class Display extends \Zotlabs\Web\Controller {
function get($update = 0, $load = false) {
// logger("mod-display: update = $update load = $load");
$checkjs = new \Zotlabs\Web\CheckJS(1);
if($load)
$_SESSION['loadtime'] = datetime_convert();
if(intval(get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
if(observer_prohibited()) {
notice( t('Public access denied.') . EOL);
return;
}
@@ -69,6 +65,7 @@ class Display extends \Zotlabs\Web\Controller {
'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => populate_acl($channel_acl),
'permissions' => $channel_acl,
'bang' => '',
'visitor' => true,
'profile_uid' => local_channel(),
@@ -110,12 +107,13 @@ class Display extends \Zotlabs\Web\Controller {
$x = q("select * from channel where channel_id = %d limit 1",
intval($target_item['uid'])
);
$y = q("select * from item_id where uid = %d and service = 'WEBPAGE' and iid = %d limit 1",
$y = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item.id = %d limit 1",
intval($target_item['uid']),
intval($target_item['id'])
);
if($x && $y) {
goaway(z_root() . '/page/' . $x[0]['channel_address'] . '/' . $y[0]['sid']);
goaway(z_root() . '/page/' . $x[0]['channel_address'] . '/' . $y[0]['v']);
}
else {
notice( t('Page not found.') . EOL);
@@ -185,7 +183,7 @@ class Display extends \Zotlabs\Web\Controller {
if($load || ($checkjs->disabled())) {
$r = null;
require_once('include/identity.php');
require_once('include/channel.php');
$sys = get_sys_channel();
$sysid = $sys['channel_id'];
@@ -233,7 +231,7 @@ class Display extends \Zotlabs\Web\Controller {
elseif($update && !$load) {
$r = null;
require_once('include/identity.php');
require_once('include/channel.php');
$sys = get_sys_channel();
$sysid = $sys['channel_id'];

View File

@@ -16,7 +16,24 @@ class Dreport extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
$mid = ((argc() > 1) ? argv(1) : '');
if($mid === 'push') {
$table = 'push';
$mid = ((argc() > 2) ? argv(2) : '');
if($mid) {
$i = q("select id from item where mid = '%s' and author_xchan = '%s' and uid = %d",
dbesc($mid),
dbesc($channel['channel_hash']),
intval($channel['channel_id'])
);
if($i) {
\Zotlabs\Daemon\Master::Summon([ 'Notifier', 'edit_post', $i[0]['id'] ]);
}
}
sleep(3);
goaway(z_root() . '/dreport/' . urlencode($mid));
}
if($mid === 'mail') {
$table = 'mail';
$mid = ((argc() > 2) ? argv(2) : '');
@@ -59,11 +76,7 @@ class Dreport extends \Zotlabs\Web\Controller {
notice( t('no results') . EOL);
return;
}
$o .= '<div class="generic-content-wrapper-styled">';
$o .= '<h2>' . sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...' . '</h2>';
$o .= '<table>';
for($x = 0; $x < count($r); $x++ ) {
$r[$x]['name'] = escape_tags(substr($r[$x]['dreport_recip'],strpos($r[$x]['dreport_recip'],' ')));
@@ -119,13 +132,25 @@ class Dreport extends \Zotlabs\Web\Controller {
}
usort($r,'self::dreport_gravity_sort');
$entries = array();
foreach($r as $rr) {
$o .= '<tr><td width="40%">' . $rr['name'] . '</td><td width="20%">' . escape_tags($rr['dreport_result']) . '</td><td width="20%">' . escape_tags($rr['dreport_time']) . '</td></tr>';
$entries[] = [
'name' => $rr['name'],
'result' => escape_tags($rr['dreport_result']),
'time' => escape_tags(datetime_convert('UTC',date_default_timezone_get(),$rr['dreport_time']))
];
}
$o .= '</table>';
$o .= '</div>';
$o = replace_macros(get_markup_template('dreport.tpl'), array(
'$title' => sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...',
'$table' => $table,
'$mid' => urlencode($mid),
'$options' => t('Options'),
'$push' => t('Redeliver'),
'$entries' => $entries
));
return $o;

View File

@@ -1,7 +1,7 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
@@ -21,7 +21,7 @@ class Editblock extends \Zotlabs\Web\Controller {
else
return;
profile_load($a,$which);
profile_load($which);
}
@@ -85,11 +85,11 @@ class Editblock extends \Zotlabs\Web\Controller {
intval($owner)
);
if($itm) {
$item_id = q("select * from item_id where service = 'BUILDBLOCK' and iid = %d limit 1",
$item_id = q("select * from iconfig where cat = 'system' and k = 'BUILDBLOCK' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$block_title = $item_id[0]['sid'];
$block_title = $item_id[0]['v'];
}
else {
notice( t('Item not found') . EOL);

View File

@@ -1,7 +1,7 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
@@ -21,7 +21,7 @@ class Editlayout extends \Zotlabs\Web\Controller {
else
return;
profile_load($a,$which);
profile_load($which);
}
@@ -96,11 +96,12 @@ class Editlayout extends \Zotlabs\Web\Controller {
intval($owner)
);
$item_id = q("select * from item_id where service = 'PDL' and iid = %d limit 1",
$item_id = q("select * from iconfig where cat = 'system' and k = 'PDL' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$layout_title = $item_id[0]['sid'];
$layout_title = $item_id[0]['v'];
$rp = 'layouts/' . $which;

View File

@@ -47,9 +47,9 @@ class Editpost extends \Zotlabs\Web\Controller {
if(intval($itm[0]['item_obscured'])) {
$key = get_config('system','prvkey');
if($itm[0]['title'])
$itm[0]['title'] = crypto_unencapsulate(json_decode_plus($itm[0]['title']),$key);
$itm[0]['title'] = crypto_unencapsulate(json_decode($itm[0]['title'],true),$key);
if($itm[0]['body'])
$itm[0]['body'] = crypto_unencapsulate(json_decode_plus($itm[0]['body']),$key);
$itm[0]['body'] = crypto_unencapsulate(json_decode($itm[0]['body'],true),$key);
}
$category = '';
@@ -87,11 +87,11 @@ class Editpost extends \Zotlabs\Web\Controller {
'hide_location' => true,
'mimetype' => $itm[0]['mimetype'],
'ptyp' => $itm[0]['obj_type'],
'body' => undo_post_tagging($itm[0]['body']),
'body' => htmlspecialchars_decode(undo_post_tagging($itm[0]['body']),ENT_COMPAT),
'post_id' => $post_id,
'defloc' => $channel['channel_location'],
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'title' => htmlspecialchars_decode($itm[0]['title'],ENT_COMPAT),
'category' => $category,
'showacl' => false,
'profile_uid' => $owner_uid,

View File

@@ -1,10 +1,9 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
require_once('include/PermissionDescription.php');
class Editwebpage extends \Zotlabs\Web\Controller {
@@ -23,7 +22,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
else
return;
profile_load($a,$which);
profile_load($which);
}
@@ -109,16 +108,16 @@ class Editwebpage extends \Zotlabs\Web\Controller {
if(intval($itm[0]['item_obscured'])) {
$key = get_config('system','prvkey');
if($itm[0]['title'])
$itm[0]['title'] = crypto_unencapsulate(json_decode_plus($itm[0]['title']),$key);
$itm[0]['title'] = crypto_unencapsulate(json_decode($itm[0]['title'],true),$key);
if($itm[0]['body'])
$itm[0]['body'] = crypto_unencapsulate(json_decode_plus($itm[0]['body']),$key);
$itm[0]['body'] = crypto_unencapsulate(json_decode($itm[0]['body'],true),$key);
}
$item_id = q("select * from item_id where service = 'WEBPAGE' and iid = %d limit 1",
$item_id = q("select * from iconfig where cat = 'system' and k = 'WEBPAGE' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$page_title = $item_id[0]['sid'];
$page_title = $item_id[0]['v'];
$mimetype = $itm[0]['mimetype'];
@@ -151,7 +150,8 @@ class Editwebpage extends \Zotlabs\Web\Controller {
'body' => undo_post_tagging($itm[0]['body']),
'post_id' => $post_id,
'visitor' => ($is_owner) ? true : false,
'acl' => populate_acl($itm[0],false,\PermissionDescription::fromGlobalPermission('view_pages')),
'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
'permissions' => $itm[0],
'showacl' => ($is_owner) ? true : false,
'mimetype' => $mimetype,
'mimeselect' => true,

View File

@@ -0,0 +1,182 @@
<?php
namespace Zotlabs\Module;
/**
*
* This is the POST destination for the embedphotos button
*
*/
class Embedphotos extends \Zotlabs\Web\Controller {
function get() {
}
function post() {
if (argc() > 1 && argv(1) === 'album') {
// API: /embedphotos/album
$name = (x($_POST,'name') ? $_POST['name'] : null );
if (!$name) {
json_return_and_die(array('errormsg' => 'Error retrieving album', 'status' => false));
}
$album = $this->embedphotos_widget_album(array('channel' => \App::get_channel(), 'album' => $name));
json_return_and_die(array('status' => true, 'content' => $album));
}
if (argc() > 1 && argv(1) === 'albumlist') {
// API: /embedphotos/albumlist
$album_list = $this->embedphotos_album_list($a);
json_return_and_die(array('status' => true, 'albumlist' => $album_list));
}
if (argc() > 1 && argv(1) === 'photolink') {
// API: /embedphotos/photolink
$href = (x($_POST,'href') ? $_POST['href'] : null );
if (!$href) {
json_return_and_die(array('errormsg' => 'Error retrieving link ' . $href, 'status' => false));
}
$resource_id = array_pop(explode("/", $href));
$r = q("SELECT obj,body from item where resource_type = 'photo' and resource_id = '%s' limit 1",
dbesc($resource_id)
);
if(!$r) {
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
}
$obj = json_decode($r[0]['obj'], true);
if(x($obj,'body')) {
$photolink = $obj['body'];
} elseif (x($obj,'bbcode')) {
$photolink = $obj['bbcode'];
} elseif ($r[0]['body'] !== '') {
$photolink = $r[0]['body'];
} else {
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
}
json_return_and_die(array('status' => true, 'photolink' => $photolink));
}
}
/**
* Copied from include/widgets.php::widget_album() with a modification to get the profile_uid from
* the input array as in widget_item()
* @param type $name
* @return string
*/
function embedphotos_widget_album($args) {
$channel_id = 0;
if(array_key_exists('channel',$args))
$channel = $args['channel'];
$channel_id = intval($channel['channel_id']);
if(! $channel_id)
$channel_id = \App::$profile_uid;
if(! $channel_id)
return '';
$owner_uid = $channel_id;
require_once('include/security.php');
$sql_extra = permissions_sql($channel_id);
if(! perm_is_allowed($channel_id,get_observer_hash(),'view_storage'))
return '';
if($args['album'])
$album = (($args['album'] === '/') ? '' : $args['album'] );
if($args['title'])
$title = $args['title'];
/**
* This may return incorrect permissions if you have multiple directories of the same name.
* It is a limitation of the photo table using a name for a photo album instead of a folder hash
*/
if($album) {
$x = q("select hash from attach where filename = '%s' and uid = %d limit 1",
dbesc($album),
intval($owner_uid)
);
if($x) {
$y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']);
if(! $y)
return '';
}
}
$order = 'DESC';
$r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN
(SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph
ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale)
ORDER BY created $order",
intval($owner_uid),
dbesc($album),
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE)
);
$photos = array();
if(count($r)) {
$twist = 'rotright';
foreach($r as $rr) {
if($twist == 'rotright')
$twist = 'rotleft';
else
$twist = 'rotright';
$ext = $phototypes[$rr['mimetype']];
$imgalt_e = $rr['filename'];
$desc_e = $rr['description'];
$imagelink = (z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id']
. (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''));
$photos[] = array(
'id' => $rr['id'],
'twist' => ' ' . $twist . rand(2,4),
'link' => $imagelink,
'title' => t('View Photo'),
'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['imgscale'] . '.' .$ext,
'alt' => $imgalt_e,
'desc'=> $desc_e,
'ext' => $ext,
'hash'=> $rr['resource_id'],
'unknown' => t('Unknown')
);
}
}
$tpl = get_markup_template('photo_album.tpl');
$o .= replace_macros($tpl, array(
'$photos' => $photos,
'$album' => (($title) ? $title : $album),
'$album_id' => rand(),
'$album_edit' => array(t('Edit Album'), $album_edit),
'$can_post' => false,
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)),
'$order' => false,
'$upload_form' => $upload_form,
'$no_fullscreen_btn' => true
));
return $o;
}
function embedphotos_album_list($a) {
$o = '';
require_once('include/photos.php');
$p = photos_albums_list(\App::get_channel(), \App::get_observer());
if ($p['success']) {
return $p['albums'];
} else {
return null;
}
}
}

View File

@@ -6,7 +6,6 @@ require_once('include/bbcode.php');
require_once('include/datetime.php');
require_once('include/event.php');
require_once('include/items.php');
require_once('include/PermissionDescription.php');
class Events extends \Zotlabs\Web\Controller {
@@ -171,7 +170,7 @@ class Events extends \Zotlabs\Web\Controller {
foreach($cats as $cat) {
$post_tags[] = array(
'uid' => $profile_uid,
'type' => TERM_CATEGORY,
'ttype' => TERM_CATEGORY,
'otype' => TERM_OBJ_POST,
'term' => trim($cat),
'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
@@ -180,12 +179,12 @@ class Events extends \Zotlabs\Web\Controller {
}
$datarray = array();
$datarray['start'] = $start;
$datarray['finish'] = $finish;
$datarray['dtstart'] = $start;
$datarray['dtend'] = $finish;
$datarray['summary'] = $summary;
$datarray['description'] = $desc;
$datarray['location'] = $location;
$datarray['type'] = $type;
$datarray['etype'] = $type;
$datarray['adjust'] = $adjust;
$datarray['nofinish'] = $nofinish;
$datarray['uid'] = local_channel();
@@ -232,7 +231,7 @@ class Events extends \Zotlabs\Web\Controller {
}
if($share)
proc_run('php',"include/notifier.php","event","$item_id");
\Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
}
@@ -269,14 +268,14 @@ class Events extends \Zotlabs\Web\Controller {
nav_set_selected('all_events');
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
$r = q("update event set ignore = 1 where id = %d and uid = %d",
$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 ignore = 0 where id = %d and uid = %d",
$r = q("update event set dismissed = 0 where id = %d and uid = %d",
intval(argv(2)),
intval(local_channel())
);
@@ -301,7 +300,7 @@ class Events extends \Zotlabs\Web\Controller {
$mode = 'view';
$y = 0;
$m = 0;
$ignored = ((x($_REQUEST,'ignored')) ? " and ignored = " . intval($_REQUEST['ignored']) . " " : '');
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
// logger('args: ' . print_r(\App::$argv,true));
@@ -358,9 +357,9 @@ class Events extends \Zotlabs\Web\Controller {
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['start'] = $_REQUEST['start'];
if(x($_REQUEST,'finish')) $orig_event['finish'] = $_REQUEST['finish'];
if(x($_REQUEST,'type')) $orig_event['type'] = $_REQUEST['type'];
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" ' : '');
@@ -380,9 +379,9 @@ class Events extends \Zotlabs\Web\Controller {
if($orig_event['event_xchan'])
$sh_checked .= ' disabled="disabled" ';
$sdt = ((x($orig_event)) ? $orig_event['start'] : 'now');
$sdt = ((x($orig_event)) ? $orig_event['dtstart'] : 'now');
$fdt = ((x($orig_event)) ? $orig_event['finish'] : '+1 hour');
$fdt = ((x($orig_event)) ? $orig_event['dtend'] : '+1 hour');
$tz = date_default_timezone_get();
if(x($orig_event))
@@ -406,7 +405,7 @@ class Events extends \Zotlabs\Web\Controller {
$ftext = datetime_convert('UTC',$tz,$fdt);
$ftext = substr($ftext,0,14) . "00:00";
$type = ((x($orig_event)) ? $orig_event['type'] : 'event');
$type = ((x($orig_event)) ? $orig_event['etype'] : 'event');
$f = get_config('system','event_input_format');
if(! $f)
@@ -436,6 +435,10 @@ class Events extends \Zotlabs\Web\Controller {
$acl = new \Zotlabs\Access\AccessList($channel);
$perm_defaults = $acl->get();
$permissions = ((x($orig_event)) ? $orig_event : $perm_defaults);
//print_r(acl2json($permissions['allow_gid'])); killme();
$tpl = get_markup_template('event_form.tpl');
@@ -468,10 +471,16 @@ class Events extends \Zotlabs\Web\Controller {
'$sh_checked' => $sh_checked,
'$share' => array('share', t('Share this event'), $sh_checked, '', array(t('No'),t('Yes'))),
'$preview' => t('Preview'),
'$permissions' => t('Permission settings'),
'$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, \PermissionDescription::fromGlobalPermission('view_stream'))),
'$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']),
'$submit' => t('Submit'),
'$advanced' => t('Advanced Options')
@@ -536,8 +545,8 @@ class Events extends \Zotlabs\Web\Controller {
);
} elseif($export) {
$r = q("SELECT * from event where uid = %d
AND (( `adjust` = 0 AND ( `finish` >= '%s' or nofinish = 1 ) AND `start` <= '%s' )
OR ( `adjust` = 1 AND ( `finish` >= '%s' or nofinish = 1 ) AND `start` <= '%s' )) ",
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),
@@ -554,8 +563,8 @@ class Events extends \Zotlabs\Web\Controller {
$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 $ignored
AND (( adjust = 0 AND ( finish >= '%s' or nofinish = 1 ) AND start <= '%s' )
OR ( adjust = 1 AND ( finish >= '%s' or nofinish = 1 ) AND start <= '%s' )) ",
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),
@@ -576,7 +585,7 @@ class Events extends \Zotlabs\Web\Controller {
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j'));
$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;
}
@@ -591,15 +600,15 @@ class Events extends \Zotlabs\Web\Controller {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j'));
$d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], $fmt) : datetime_convert('UTC','UTC',$rr['start'],$fmt));
$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['start'], 'c') : datetime_convert('UTC','UTC',$rr['start'],'c'));
$start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'c') : datetime_convert('UTC','UTC',$rr['dtstart'],'c'));
if ($rr['nofinish']){
$end = null;
} else {
$end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['finish'], 'c') : datetime_convert('UTC','UTC',$rr['finish'],'c'));
$end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c'));
}
@@ -668,8 +677,10 @@ class Events extends \Zotlabs\Web\Controller {
'$export' => array(z_root()."/events/$y/$m/export",t('Export'),'',''),
'$calendar' => cal($y,$m,$links, ' eventcal'),
'$events' => $events,
'$upload' => t('Import'),
'$submit' => t('Submit'),
'$view_label' => t('View'),
'$month' => t('Month'),
'$week' => t('Week'),
'$day' => t('Day'),
'$prev' => t('Previous'),
'$next' => t('Next'),
'$today' => t('Today'),

View File

@@ -45,10 +45,10 @@ class Fbrowser extends \Zotlabs\Web\Controller {
$album = hex2bin(\App::$argv[2]);
$sql_extra = sprintf("AND `album` = '%s' ",dbesc($album));
$sql_extra2 = "";
$path[]=array(z_root()."/fbrowser/image/".\App::$argv[2]."/", $album);
$path[]=array(z_root() . "/fbrowser/image/" . \App::$argv[2] . "/", $album);
}
$r = q("SELECT `resource_id`, `id`, `filename`, type, min(`scale`) AS `hiq`,max(`scale`) AS `loq`, `description`
$r = q("SELECT `resource_id`, `id`, `filename`, type, min(`imgscale`) AS `hiq`,max(`imgscale`) AS `loq`, `description`
FROM `photo` WHERE `uid` = %d $sql_extra
GROUP BY `resource_id` $sql_extra2",
intval(local_channel())

View File

@@ -31,7 +31,7 @@ class Feed extends \Zotlabs\Web\Controller {
$channel = $r[0];
if((intval(get_config('system','block_public'))) && (! get_account_id()))
if(observer_prohibited(true))
killme();
logger('mod_feed: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']);

View File

@@ -0,0 +1,45 @@
<?php
namespace Zotlabs\Module;
require_once('include/attach.php');
require_once('include/channel.php');
require_once('include/photos.php');
class File_upload extends \Zotlabs\Web\Controller {
function post() {
// logger('file upload: ' . print_r($_REQUEST,true));
$channel = (($_REQUEST['channick']) ? get_channel_by_nick($_REQUEST['channick']) : null);
if(! $channel) {
logger('channel not found');
killme();
}
$_REQUEST['source'] = 'file_upload';
if($channel['channel_id'] != local_channel()) {
$_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']);
$_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']);
$_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']);
$_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']);
}
if($_REQUEST['filename']) {
$_REQUEST['allow_cid'] = perms2str($_REQUEST['contact_allow']);
$_REQUEST['allow_gid'] = perms2str($_REQUEST['group_allow']);
$_REQUEST['deny_cid'] = perms2str($_REQUEST['contact_deny']);
$_REQUEST['deny_gid'] = perms2str($_REQUEST['group_deny']);
$r = attach_mkdir($channel,get_observer_hash(),$_REQUEST);
}
else {
$r = attach_store($channel,get_observer_hash(), '', $_REQUEST);
}
goaway(z_root() . '/' . $_REQUEST['return_url']);
}
}

View File

@@ -39,7 +39,7 @@ class Filer extends \Zotlabs\Web\Controller {
}
else {
$filetags = array();
$r = q("select distinct(term) from term where uid = %d and type = %d order by term asc",
$r = q("select distinct(term) from term where uid = %d and ttype = %d order by term asc",
intval(local_channel()),
intval(TERM_FILE)
);

View File

@@ -22,7 +22,7 @@ class Filerm extends \Zotlabs\Web\Controller {
logger('filerm: tag ' . $term . ' item ' . $item_id);
if($item_id && strlen($term)) {
$r = q("delete from term where uid = %d and type = %d and oid = %d and term = '%s'",
$r = q("delete from term where uid = %d and ttype = %d and oid = %d and term = '%s'",
intval(local_channel()),
intval(($category) ? TERM_CATEGORY : TERM_FILE),
intval($item_id),

View File

@@ -6,7 +6,6 @@ namespace Zotlabs\Module;
*/
require_once('include/attach.php');
require_once('include/PermissionDescription.php');
/**
@@ -134,7 +133,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
$cloudpath = get_cloudpath($f) . (intval($f['is_dir']) ? '?f=&davguest=1' : '');
$parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']);
$aclselect_e = populate_acl($f, false, \PermissionDescription::fromGlobalPermission('view_storage'));
$aclselect_e = populate_acl($f, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage'));
$is_a_dir = (intval($f['is_dir']) ? true : false);
$lockstate = (($f['allow_cid'] || $f['allow_gid'] || $f['deny_cid'] || $f['deny_gid']) ? 'lock' : 'unlock');
@@ -142,7 +141,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
// Encode path that is used for link so it's a valid URL
// Keep slashes as slashes, otherwise mod_rewrite doesn't work correctly
$encoded_path = str_replace('%2F', '/', rawurlencode($cloudpath));
$o = replace_macros(get_markup_template('attach_edit.tpl'), array(
'$header' => t('Edit file permissions'),
'$file' => $f,
@@ -152,6 +151,10 @@ class Filestorage extends \Zotlabs\Web\Controller {
'$channelnick' => $channel['channel_address'],
'$permissions' => t('Permissions'),
'$aclselect' => $aclselect_e,
'$allow_cid' => acl2json($f['allow_cid']),
'$allow_gid' => acl2json($f['allow_gid']),
'$deny_cid' => acl2json($f['deny_cid']),
'$deny_gid' => acl2json($f['deny_gid']),
'$lockstate' => $lockstate,
'$permset' => t('Set/edit permissions'),
'$recurse' => array('recurse', t('Include all files and sub folders'), 0, '', array(t('No'), t('Yes'))),
@@ -162,7 +165,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
'$submit' => t('Submit'),
'$attach_btn_title' => t('Share this file'),
'$link_btn_title' => t('Show URL to this file'),
'$notify' => array('notify', t('Notify your contacts about this file'), 0, '', array(t('No'), t('Yes')))
'$notify' => array('notify', t('Notify your contacts about this file'), 0, '', array(t('No'), t('Yes'))),
));
echo $o;

View File

@@ -43,24 +43,24 @@ class Follow extends \Zotlabs\Web\Controller {
unset($clone['abook_account']);
unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_hash'],$clone['abook_xchan']);
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
if($abconfig)
$clone['abconfig'] = $abconfig;
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)), true);
$can_view_stream = intval(get_abconfig($channel['channel_id'],$clone['abook_xchan'],'their_perms','view_stream'));
// If we can view their stream, pull in some posts
if(($result['abook']['abook_their_perms'] & PERMS_R_STREAM) || ($result['abook']['xchan_network'] === 'rss'))
proc_run('php','include/onepoll.php',$result['abook']['abook_id']);
if(($can_view_stream) || ($result['abook']['xchan_network'] === 'rss'))
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$result['abook']['abook_id']));
goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?f=&follow=1');
}
function get() {
function get() {
if(! local_channel()) {
return login();
}

View File

@@ -1,117 +0,0 @@
<?php
namespace Zotlabs\Module;
class Fsuggest extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel()) {
return;
}
if(\App::$argc != 2)
return;
$contact_id = intval(\App::$argv[1]);
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($contact_id),
intval(local_channel())
);
if(! count($r)) {
notice( t('Contact not found.') . EOL);
return;
}
$contact = $r[0];
$new_contact = intval($_POST['suggest']);
$hash = random_string();
$note = escape_tags(trim($_POST['note']));
if($new_contact) {
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($new_contact),
intval(local_channel())
);
if(count($r)) {
$x = q("INSERT INTO `fsuggest` ( `uid`,`cid`,`name`,`url`,`request`,`photo`,`note`,`created`)
VALUES ( %d, %d, '%s','%s','%s','%s','%s','%s')",
intval(local_channel()),
intval($contact_id),
dbesc($r[0]['name']),
dbesc($r[0]['url']),
dbesc($r[0]['request']),
dbesc($r[0]['photo']),
dbesc($hash),
dbesc(datetime_convert())
);
$r = q("SELECT `id` FROM `fsuggest` WHERE `note` = '%s' AND `uid` = %d LIMIT 1",
dbesc($hash),
intval(local_channel())
);
if(count($r)) {
$fsuggest_id = $r[0]['id'];
q("UPDATE `fsuggest` SET `note` = '%s' WHERE `id` = %d AND `uid` = %d",
dbesc($note),
intval($fsuggest_id),
intval(local_channel())
);
proc_run('php', 'include/notifier.php', 'suggest' , $fsuggest_id);
}
info( t('Friend suggestion sent.') . EOL);
}
}
}
function get() {
require_once('include/acl_selectors.php');
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if(\App::$argc != 2)
return;
$contact_id = intval(\App::$argv[1]);
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($contact_id),
intval(local_channel())
);
if(! count($r)) {
notice( t('Contact not found.') . EOL);
return;
}
$contact = $r[0];
$o = '<h3>' . t('Suggest Friends') . '</h3>';
$o .= '<div id="fsuggest-desc" >' . sprintf( t('Suggest a friend for %s'), $contact['name']) . '</div>';
$o .= '<form id="fsuggest-form" action="fsuggest/' . $contact_id . '" method="post" >';
// FIXME contact_selector deprecated, removed
// $o .= contact_selector('suggest','suggest-select', false,
// array('size' => 4, 'exclude' => $contact_id, 'networks' => 'DFRN_ONLY', 'single' => true));
$o .= '<div id="fsuggest-submit-wrapper"><input id="fsuggest-submit" type="submit" name="submit" value="' . t('Submit') . '" /></div>';
$o .= '</form>';
return $o;
}
}

View File

@@ -21,7 +21,6 @@ namespace Zotlabs\Module;
require_once('include/Contact.php');
require_once('include/attach.php');

View File

@@ -47,8 +47,8 @@ class Group extends \Zotlabs\Web\Controller {
$groupname = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
if((strlen($groupname)) && (($groupname != $group['name']) || ($public != $group['visible']))) {
$r = q("UPDATE `groups` SET `name` = '%s', visible = %d WHERE `uid` = %d AND `id` = %d",
if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
$r = q("UPDATE `groups` SET `gname` = '%s', visible = %d WHERE `uid` = %d AND `id` = %d",
dbesc($groupname),
intval($public),
intval(local_channel()),
@@ -101,12 +101,12 @@ class Group extends \Zotlabs\Web\Controller {
check_form_security_token_redirectOnErr('/group', 'group_drop', 't');
if(intval(argv(2))) {
$r = q("SELECT `name` FROM `groups` WHERE `id` = %d AND `uid` = %d LIMIT 1",
$r = q("SELECT `gname` FROM `groups` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval(argv(2)),
intval(local_channel())
);
if($r)
$result = group_rmv(local_channel(),$r[0]['name']);
$result = group_rmv(local_channel(),$r[0]['gname']);
if($result)
info( t('Privacy group removed.') . EOL);
else
@@ -156,10 +156,10 @@ class Group extends \Zotlabs\Web\Controller {
if($change) {
if(in_array($change,$preselected)) {
group_rmv_member(local_channel(),$group['name'],$change);
group_rmv_member(local_channel(),$group['gname'],$change);
}
else {
group_add_member(local_channel(),$group['name'],$change);
group_add_member(local_channel(),$group['gname'],$change);
}
$members = group_get_members($group['id']);
@@ -181,7 +181,7 @@ class Group extends \Zotlabs\Web\Controller {
$context = $context + array(
'$title' => t('Privacy group editor'),
'$gname' => array('groupname',t('Privacy group name: '),$group['name'], ''),
'$gname' => array('groupname',t('Privacy group name: '),$group['gname'], ''),
'$gid' => $group['id'],
'$drop' => $drop_txt,
'$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''),
@@ -209,7 +209,7 @@ class Group extends \Zotlabs\Web\Controller {
$groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode);
}
else
group_rmv_member(local_channel(),$group['name'],$member['xchan_hash']);
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",

View File

@@ -40,7 +40,7 @@ class Hcard extends \Zotlabs\Web\Controller {
}
}
profile_load($a,$which,$profile);
profile_load($which,$profile);
}

View File

@@ -37,7 +37,7 @@ class Help extends \Zotlabs\Web\Controller {
$path = trim(substr($dirname,4),'/');
$o .= '<li><a href="help/' . (($path) ? $path . '/' : '') . $fname . '" >' . ucwords(str_replace('_',' ',notags($fname))) . '</a><br />' .
str_replace('$Projectname',\Zotlabs\Project\System::get_platform_name(),substr($rr['text'],0,200)) . '...<br /><br /></li>';
str_replace('$Projectname',\Zotlabs\Lib\System::get_platform_name(),substr($rr['text'],0,200)) . '...<br /><br /></li>';
}
$o .= '</ul>';

View File

@@ -28,6 +28,19 @@ class Home extends \Zotlabs\Web\Controller {
goaway($dest);
}
if(remote_channel() && (! $splash) && $_SESSION['atoken']) {
$r = q("select * from atoken where atoken_id = %d",
intval($_SESSION['atoken'])
);
if($r) {
$x = channelx_by_n($r[0]['atoken_uid']);
if($x) {
goaway(z_root() . '/channel/' . $x['channel_address']);
}
}
}
if(get_account_id() && ! $splash) {
goaway(z_root() . '/new_channel');

View File

@@ -1,319 +0,0 @@
<?php
namespace Zotlabs\Module;
/**
* @file mod/id.php
* @brief OpenID implementation
*/
require 'library/openid/provider/provider.php';
$attrMap = array(
'namePerson/first' => t('First Name'),
'namePerson/last' => t('Last Name'),
'namePerson/friendly' => t('Nickname'),
'namePerson' => t('Full Name'),
'contact/internet/email' => t('Email'),
'contact/email' => t('Email'),
'media/image/aspect11' => t('Profile Photo'),
'media/image' => t('Profile Photo'),
'media/image/default' => t('Profile Photo'),
'media/image/16x16' => t('Profile Photo 16px'),
'media/image/32x32' => t('Profile Photo 32px'),
'media/image/48x48' => t('Profile Photo 48px'),
'media/image/64x64' => t('Profile Photo 64px'),
'media/image/80x80' => t('Profile Photo 80px'),
'media/image/128x128' => t('Profile Photo 128px'),
'timezone' => t('Timezone'),
'contact/web/default' => t('Homepage URL'),
'language/pref' => t('Language'),
'birthDate/birthYear' => t('Birth Year'),
'birthDate/birthMonth' => t('Birth Month'),
'birthDate/birthday' => t('Birth Day'),
'birthDate' => t('Birthdate'),
'gender' => t('Gender'),
);
/**
* @brief Entrypoint for the OpenID implementation.
*
* @param App &$a
*/
class Id extends \Zotlabs\Web\Controller {
function init() {
logger('id: ' . print_r($_REQUEST, true));
if(argc() > 1) {
$which = argv(1);
} else {
\App::$error = 404;
return;
}
$profile = '';
$channel = \App::get_channel();
profile_load($a,$which,$profile);
$op = new MysqlProvider;
$op->server();
}
/**
* @brief Returns user data needed for OpenID.
*
* If no $handle is provided we will use local_channel() by default.
*
* @param string $handle (default null)
* @return boolean|array
*/
static public function getUserData($handle = null) {
if (! local_channel()) {
notice( t('Permission denied.') . EOL);
\App::$page['content'] = login();
return false;
}
// logger('handle: ' . $handle);
if ($handle) {
$r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1",
dbesc($handle)
);
} else {
$r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d",
intval(local_channel())
);
}
if (! r)
return false;
$x = q("select * from account where account_id = %d limit 1",
intval($r[0]['channel_account_id'])
);
if ($x)
$r[0]['email'] = $x[0]['account_email'];
$p = q("select * from profile where is_default = 1 and uid = %d limit 1",
intval($r[0]['channel_account_id'])
);
$gender = '';
if ($p[0]['gender'] == t('Male'))
$gender = 'M';
if ($p[0]['gender'] == t('Female'))
$gender = 'F';
$r[0]['firstName'] = ((strpos($r[0]['channel_name'],' ')) ? substr($r[0]['channel_name'],0,strpos($r[0]['channel_name'],' ')) : $r[0]['channel_name']);
$r[0]['lastName'] = ((strpos($r[0]['channel_name'],' ')) ? substr($r[0]['channel_name'],strpos($r[0]['channel_name'],' ')+1) : '');
$r[0]['namePerson'] = $r[0]['channel_name'];
$r[0]['pphoto'] = $r[0]['xchan_photo_l'];
$r[0]['pphoto16'] = z_root() . '/photo/profile/16/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto32'] = z_root() . '/photo/profile/32/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto48'] = z_root() . '/photo/profile/48/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto64'] = z_root() . '/photo/profile/64/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto80'] = z_root() . '/photo/profile/80/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto128'] = z_root() . '/photo/profile/128/' . $r[0]['channel_id'] . '.jpg';
$r[0]['timezone'] = $r[0]['channel_timezone'];
$r[0]['url'] = $r[0]['xchan_url'];
$r[0]['language'] = (($x[0]['account_language']) ? $x[0]['account_language'] : 'en');
$r[0]['birthyear'] = ((intval(substr($p[0]['dob'],0,4))) ? intval(substr($p[0]['dob'],0,4)) : '');
$r[0]['birthmonth'] = ((intval(substr($p[0]['dob'],5,2))) ? intval(substr($p[0]['dob'],5,2)) : '');
$r[0]['birthday'] = ((intval(substr($p[0]['dob'],8,2))) ? intval(substr($p[0]['dob'],8,2)) : '');
$r[0]['birthdate'] = (($r[0]['birthyear'] && $r[0]['birthmonth'] && $r[0]['birthday']) ? $p[0]['dob'] : '');
$r[0]['gender'] = $gender;
return $r[0];
/*
* if(isset($_POST['login'],$_POST['password'])) {
* $login = mysql_real_escape_string($_POST['login']);
* $password = sha1($_POST['password']);
* $q = mysql_query("SELECT * FROM Users WHERE login = '$login' AND password = '$password'");
* if($data = mysql_fetch_assoc($q)) {
* return $data;
* }
* if($handle) {
* echo 'Wrong login/password.';
* }
* }
* if($handle) {
* ?>
* <form action="" method="post">
* <input type="hidden" name="openid.assoc_handle" value="<?php
namespace Zotlabs\Module; echo $handle?>">
* Login: <input type="text" name="login"><br>
* Password: <input type="password" name="password"><br>
* <button>Submit</button>
* </form>
* <?php
namespace Zotlabs\Module;
* die();
* }
*/
}
}
/**
* @brief MySQL provider for OpenID implementation.
*
*/
class MysqlProvider extends \LightOpenIDProvider {
// See http://openid.net/specs/openid-attribute-properties-list-1_0-01.html
// This list contains a few variations of these attributes to maintain
// compatibility with legacy clients
private $attrFieldMap = array(
'namePerson/first' => 'firstName',
'namePerson/last' => 'lastName',
'namePerson/friendly' => 'channel_address',
'namePerson' => 'namePerson',
'contact/internet/email' => 'email',
'contact/email' => 'email',
'media/image/aspect11' => 'pphoto',
'media/image' => 'pphoto',
'media/image/default' => 'pphoto',
'media/image/16x16' => 'pphoto16',
'media/image/32x32' => 'pphoto32',
'media/image/48x48' => 'pphoto48',
'media/image/64x64' => 'pphoto64',
'media/image/80x80' => 'pphoto80',
'media/image/128x128' => 'pphoto128',
'timezone' => 'timezone',
'contact/web/default' => 'url',
'language/pref' => 'language',
'birthDate/birthYear' => 'birthyear',
'birthDate/birthMonth' => 'birthmonth',
'birthDate/birthday' => 'birthday',
'birthDate' => 'birthdate',
'gender' => 'gender',
);
function setup($identity, $realm, $assoc_handle, $attributes) {
global $attrMap;
// logger('identity: ' . $identity);
// logger('realm: ' . $realm);
// logger('assoc_handle: ' . $assoc_handle);
// logger('attributes: ' . print_r($attributes,true));
$data = \Zotlabs\Module\Id::getUserData($assoc_handle);
/** @FIXME this needs to be a template with localised strings */
$o .= '<form action="" method="post">'
. '<input type="hidden" name="openid.assoc_handle" value="' . $assoc_handle . '">'
. '<input type="hidden" name="login" value="' . $_POST['login'] .'">'
. '<input type="hidden" name="password" value="' . $_POST['password'] .'">'
. "<b>$realm</b> wishes to authenticate you.";
if($attributes['required'] || $attributes['optional']) {
$o .= " It also requests following information (required fields marked with *):"
. '<ul>';
foreach($attributes['required'] as $attr) {
if(isset($this->attrMap[$attr])) {
$o .= '<li>'
. '<input type="checkbox" name="attributes[' . $attr . ']"> '
. $this->attrMap[$attr] . ' <span class="required">*</span></li>';
}
}
foreach($attributes['optional'] as $attr) {
if(isset($this->attrMap[$attr])) {
$o .= '<li>'
. '<input type="checkbox" name="attributes[' . $attr . ']"> '
. $this->attrMap[$attr] . '</li>';
}
}
$o .= '</ul>';
}
$o .= '<br>'
. '<button name="once">Allow once</button> '
. '<button name="always">Always allow</button> '
. '<button name="cancel">cancel</button> '
. '</form>';
\App::$page['content'] .= $o;
}
function checkid($realm, &$attributes) {
logger('checkid: ' . $realm);
logger('checkid attrs: ' . print_r($attributes,true));
if(isset($_POST['cancel'])) {
$this->cancel();
}
$data = \Zotlabs\Module\Id::getUserData();
if(! $data) {
return false;
}
$q = get_pconfig(local_channel(), 'openid', $realm);
$attrs = array();
if($q) {
$attrs = $q;
} elseif(isset($_POST['attributes'])) {
$attrs = array_keys($_POST['attributes']);
} elseif(!isset($_POST['once']) && !isset($_POST['always'])) {
return false;
}
$attributes = array();
foreach($attrs as $attr) {
if(isset($this->attrFieldMap[$attr])) {
$attributes[$attr] = $data[$this->attrFieldMap[$attr]];
}
}
if(isset($_POST['always'])) {
set_pconfig(local_channel(),'openid',$realm,array_keys($attributes));
}
return z_root() . '/id/' . $data['channel_address'];
}
function assoc_handle() {
logger('assoc_handle');
$channel = \App::get_channel();
return z_root() . '/channel/' . $channel['channel_address'];
}
function setAssoc($handle, $data) {
logger('setAssoc');
$channel = channelx_by_nick(basename($handle));
if($channel)
set_pconfig($channel['channel_id'],'openid','associate',$data);
}
function getAssoc($handle) {
logger('getAssoc: ' . $handle);
$channel = channelx_by_nick(basename($handle));
if($channel)
return get_pconfig($channel['channel_id'], 'openid', 'associate');
return false;
}
function delAssoc($handle) {
logger('delAssoc');
$channel = channelx_by_nick(basename($handle));
if($channel)
return del_pconfig($channel['channel_id'], 'openid', 'associate');
}
}

View File

@@ -88,7 +88,11 @@ class Impel extends \Zotlabs\Web\Controller {
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']);
$mitem['mitem_link'] = str_replace('[baseurl]',z_root(),$it['link']);
$mitem['mitem_desc'] = escape_tags($it['desc']);
$mitem['mitem_order'] = intval($it['order']);
if(is_array($it['flags'])) {
@@ -137,9 +141,7 @@ class Impel extends \Zotlabs\Web\Controller {
require_once('library/urlify/URLify.php');
$pagetitle = strtolower(\URLify::transliterate($j['pagetitle']));
}
// Verify ability to use html or php!!!
$execflag = false;
@@ -154,21 +156,14 @@ class Impel extends \Zotlabs\Web\Controller {
}
}
$remote_id = 0;
$z = q("select * from item_id where sid = '%s' and service = '%s' and uid = %d limit 1",
dbesc($pagetitle),
dbesc($namespace),
intval(local_channel())
);
$i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['mid']),
intval(local_channel())
);
\Zotlabs\Lib\IConfig::Set($arr,'system',$namespace,(($pagetitle) ? $pagetitle : substr($arr['mid'],0,16)),true);
if($z && $i) {
$remote_id = $z[0]['id'];
if($i) {
$arr['id'] = $i[0]['id'];
// don't update if it has the same timestamp as the original
if($arr['edited'] > $i[0]['edited'])
@@ -182,12 +177,12 @@ class Impel extends \Zotlabs\Web\Controller {
intval(local_channel())
);
}
$x = item_store($arr,$execflag);
else
$x = item_store($arr,$execflag);
}
if($x['success']) {
if($x && $x['success']) {
$item_id = $x['item_id'];
update_remote_id($channel,$item_id,$arr['item_type'],$pagetitle,$namespace,$remote_id,$arr['mid']);
}
}
@@ -199,7 +194,8 @@ class Impel extends \Zotlabs\Web\Controller {
notice( sprintf( t('%s element installation failed'), $installed_type));
}
//??? should perhaps return ret?
//??? should perhaps return ret?
json_return_and_die(true);
}

View File

@@ -4,10 +4,11 @@ namespace Zotlabs\Module;
// Import a channel, either by direct file upload or via
// connection to original server.
require_once('include/Contact.php');
require_once('include/zot.php');
require_once('include/identity.php');
require_once('include/channel.php');
require_once('include/import.php');
require_once('include/perm_upgrade.php');
@@ -131,6 +132,8 @@ class Import extends \Zotlabs\Web\Controller {
// import channel
$relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null);
if(array_key_exists('channel',$data)) {
if($completed < 1) {
@@ -337,6 +340,8 @@ class Import extends \Zotlabs\Web\Controller {
$abooks = $data['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']))
@@ -345,6 +350,10 @@ class Import extends \Zotlabs\Web\Controller {
unset($abook['abook_id']);
unset($abook['abook_rating']);
unset($abook['abook_rating_text']);
unset($abook['abconfig']);
unset($abook['abook_their_perms']);
unset($abook['abook_my_perms']);
$abook['abook_account'] = $account_id;
$abook['abook_channel'] = $channel['channel_id'];
if(! array_key_exists('abook_blocked',$abook)) {
@@ -383,12 +392,13 @@ class Import extends \Zotlabs\Web\Controller {
$friends ++;
if(intval($abook['abook_feed']))
$feeds ++;
translate_abook_perms_inbound($channel,$abook_copy);
if($abconfig) {
// @fixme does not handle sync of del_abconfig
foreach($abconfig as $abc) {
if($abc['chan'] === $channel['channel_hash'])
set_abconfig($abc['chan'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
}
}
@@ -408,8 +418,12 @@ class Import extends \Zotlabs\Web\Controller {
$saved = array();
foreach($groups as $group) {
$saved[$group['hash']] = array('old' => $group['id']);
if(array_key_exists('name',$group)) {
$group['gname'] = $group['name'];
unset($group['name']);
}
unset($group['id']);
$group['uid'] = $channel['channel_id'];
$group['uid'] = $channel['channel_id'];
dbesc_array($group);
$r = dbq("INSERT INTO groups (`"
. implode("`, `", array_keys($group))
@@ -471,7 +485,7 @@ class Import extends \Zotlabs\Web\Controller {
import_events($channel,$data['event']);
if(is_array($data['event_item']))
import_items($channel,$data['event_item']);
import_items($channel,$data['event_item'],false,$relocate);
if(is_array($data['menu']))
import_menus($channel,$data['menu']);
@@ -482,7 +496,7 @@ class Import extends \Zotlabs\Web\Controller {
$saved_notification_flags = notifications_off($channel['channel_id']);
if($import_posts && array_key_exists('item',$data) && $data['item'])
import_items($channel,$data['item']);
import_items($channel,$data['item'],false,$relocate);
notifications_on($channel['channel_id'],$saved_notification_flags);
@@ -496,11 +510,11 @@ class Import extends \Zotlabs\Web\Controller {
// send out refresh requests
// notify old server that it may no longer be primary.
proc_run('php','include/notifier.php','location',$channel['channel_id']);
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
// This will indirectly perform a refresh_all *and* update the directory
proc_run('php', 'include/directory.php', $channel['channel_id']);
\Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id']));
notice( t('Import completed.') . EOL);

View File

@@ -78,6 +78,8 @@ class Import_items extends \Zotlabs\Web\Controller {
// 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);
@@ -92,7 +94,7 @@ class Import_items extends \Zotlabs\Web\Controller {
if(array_key_exists('item',$data) && $data['item']) {
import_items($channel,$data['item']);
import_items($channel,$data['item'],false,((array_key_exists('relocate',$data)) ? $data['relocate'] : null));
}
if(array_key_exists('item_id',$data) && $data['item_id']) {
@@ -106,7 +108,7 @@ class Import_items extends \Zotlabs\Web\Controller {
function get() {
function get() {
if(! local_channel()) {
notice( t('Permission denied') . EOL);

View File

@@ -1,4 +1,5 @@
<?php
namespace Zotlabs\Module;
/**
@@ -17,10 +18,10 @@ namespace Zotlabs\Module;
*/
require_once('include/crypto.php');
require_once('include/enotify.php');
require_once('include/items.php');
require_once('include/attach.php');
use \Zotlabs\Lib as Zlib;
class Item extends \Zotlabs\Web\Controller {
@@ -56,7 +57,7 @@ class Item extends \Zotlabs\Web\Controller {
$remote_xchan = $remote_observer = false;
$profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0);
require_once('include/identity.php');
require_once('include/channel.php');
$sys = get_sys_channel();
if($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) {
$uid = intval($sys['channel_id']);
@@ -92,7 +93,7 @@ class Item extends \Zotlabs\Web\Controller {
$origin = (($api_source && array_key_exists('origin',$_REQUEST)) ? intval($_REQUEST['origin']) : 1);
// To represent message-ids on other networks - this will create an item_id record
// To represent message-ids on other networks - this will create an iconfig record
$namespace = (($api_source && array_key_exists('namespace',$_REQUEST)) ? strip_tags($_REQUEST['namespace']) : '');
$remote_id = (($api_source && array_key_exists('remote_id',$_REQUEST)) ? strip_tags($_REQUEST['remote_id']) : '');
@@ -182,7 +183,9 @@ class Item extends \Zotlabs\Web\Controller {
}
// can_comment_on_post() needs info from the following xchan_query
xchan_query($r);
// This may be from the discover tab which means we need to correct the effective uid
xchan_query($r,true,(($r[0]['uid'] == local_channel()) ? 0 : local_channel()));
$parent_item = $r[0];
$parent = $r[0]['id'];
@@ -229,7 +232,7 @@ class Item extends \Zotlabs\Web\Controller {
if($namespace && $remote_id) {
// It wasn't an internally generated post - see if we've got an item matching this remote service id
$i = q("select iid from item_id where service = '%s' and sid = '%s' limit 1",
$i = q("select iid from iconfig where cat = 'system' and k = '%s' and v = '%s' limit 1",
dbesc($namespace),
dbesc($remote_id)
);
@@ -315,9 +318,11 @@ class Item extends \Zotlabs\Web\Controller {
}
$acl = new \Zotlabs\Access\AccessList($channel);
$view_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream');
$comment_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'post_comments');
$public_policy = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($channel['channel_r_stream'],true));
$public_policy = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($view_policy,true));
if($webpage)
$public_policy = '';
if($public_policy)
@@ -525,16 +530,16 @@ class Item extends \Zotlabs\Web\Controller {
if((! $parent) && (get_pconfig($profile_uid,'system','tagifonlyrecip')) && (substr_count($str_contact_allow,'<') == 1) && ($str_group_allow == '') && ($str_contact_deny == '') && ($str_group_deny == '')) {
$x = q("select abook_id, abook_their_perms from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
$x = q("select abook_id, abconfig.v from abook left join abconfig on abook_xchan = abconfig.xchan and abook_channel = abconfig.chan and cat= 'their_perms' and abconfig.k = 'tag_deliver' and abconfig.v = 1 and abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc(str_replace(array('<','>'),array('',''),$str_contact_allow)),
intval($profile_uid)
);
if($x && ($x[0]['abook_their_perms'] & PERMS_W_TAGWALL))
if($x)
$body .= "\n\n@group+" . $x[0]['abook_id'] . "\n";
}
/**
* fix naked links by passing through a callback to see if this is a red site
* fix naked links by passing through a callback to see if this is a hubzilla site
* (already known to us) which will get a zrl, otherwise link with url, add bookmark tag to both.
* First protect any url inside certain bbcode tags so we don't double link it.
*/
@@ -581,7 +586,7 @@ class Item extends \Zotlabs\Web\Controller {
if($success['replaced']) {
$post_tags[] = array(
'uid' => $profile_uid,
'type' => $success['termtype'],
'ttype' => $success['termtype'],
'otype' => TERM_OBJ_POST,
'term' => $success['term'],
'url' => $success['url']
@@ -666,7 +671,7 @@ class Item extends \Zotlabs\Web\Controller {
foreach($cats as $cat) {
$post_tags[] = array(
'uid' => $profile_uid,
'type' => TERM_CATEGORY,
'ttype' => TERM_CATEGORY,
'otype' => TERM_OBJ_POST,
'term' => trim($cat),
'url' => $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
@@ -676,7 +681,7 @@ class Item extends \Zotlabs\Web\Controller {
if($orig_post) {
// preserve original tags
$t = q("select * from term where oid = %d and otype = %d and uid = %d and type in ( %d, %d, %d )",
$t = q("select * from term where oid = %d and otype = %d and uid = %d and ttype in ( %d, %d, %d )",
intval($orig_post['id']),
intval(TERM_OBJ_POST),
intval($profile_uid),
@@ -688,7 +693,7 @@ class Item extends \Zotlabs\Web\Controller {
foreach($t as $t1) {
$post_tags[] = array(
'uid' => $profile_uid,
'type' => $t1['type'],
'ttype' => $t1['type'],
'otype' => TERM_OBJ_POST,
'term' => $t1['term'],
'url' => $t1['url'],
@@ -809,7 +814,7 @@ class Item extends \Zotlabs\Web\Controller {
$datarray['layout_mid'] = $layout_mid;
$datarray['public_policy'] = $public_policy;
$datarray['comment_policy'] = map_scope($channel['channel_w_comment']);
$datarray['comment_policy'] = map_scope($comment_policy);
$datarray['term'] = $post_tags;
$datarray['plink'] = $plink;
$datarray['route'] = $route;
@@ -833,21 +838,23 @@ class Item extends \Zotlabs\Web\Controller {
if($orig_post)
$datarray['edit'] = true;
// suppress duplicates, *unless* you're editing an existing post. This could get picked up
// as a duplicate if you're editing it very soon after posting it initially and you edited
// some attribute besides the content, such as title or categories.
if(feature_enabled($profile_uid,'suppress_duplicates') && (! $orig_post)) {
$z = q("select created from item where uid = %d and body = '%s'",
$z = q("select created from item where uid = %d and created > %s - INTERVAL %s and body = '%s' limit 1",
intval($profile_uid),
db_utcnow(),
db_quoteinterval('2 MINUTE'),
dbesc($body)
);
if($z) {
foreach($z as $zz) {
if($zz['created'] > datetime_convert('UTC','UTC', 'now - 2 minutes')) {
$datarray['cancel'] = 1;
notice( t('Duplicate post suppressed.') . EOL);
logger('Duplicate post. Faking plugin cancel.');
}
}
$datarray['cancel'] = 1;
notice( t('Duplicate post suppressed.') . EOL);
logger('Duplicate post. Faking plugin cancel.');
}
}
@@ -880,13 +887,21 @@ class Item extends \Zotlabs\Web\Controller {
}
}
if($webpage) {
Zlib\IConfig::Set($datarray,'system', webpage_to_namespace($webpage),
(($pagetitle) ? $pagetitle : substr($datarray['mid'],0,16)),true);
}
elseif($namespace) {
Zlib\IConfig::Set($datarray,'system', $namespace,
(($remote_id) ? $remote_id : substr($datarray['mid'],0,16)),true);
}
if($orig_post) {
$datarray['id'] = $post_id;
item_store_update($datarray,$execflag);
update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid);
$x = item_store_update($datarray,$execflag);
if(! $parent) {
$r = q("select * from item where id = %d",
intval($post_id)
@@ -894,14 +909,11 @@ class Item extends \Zotlabs\Web\Controller {
if($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
$rid = q("select * from item_id where iid = %d",
intval($post_id)
);
build_sync_packet($uid,array('item' => array(encode_item($sync_item[0],true)),'item_id' => $rid));
build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true))));
}
}
if(! $nopush)
proc_run('php', "include/notifier.php", 'edit_post', $post_id);
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'edit_post', $post_id));
if((x($_REQUEST,'return')) && strlen($return_path)) {
logger('return: ' . $return_path);
@@ -925,7 +937,7 @@ class Item extends \Zotlabs\Web\Controller {
// otherwise it will happen during delivery
if(($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) {
notification(array(
Zlib\Enotify::submit(array(
'type' => NOTIFY_COMMENT,
'from_xchan' => $datarray['author_xchan'],
'to_xchan' => $datarray['owner_xchan'],
@@ -943,7 +955,7 @@ class Item extends \Zotlabs\Web\Controller {
$parent = $post_id;
if(($datarray['owner_xchan'] != $datarray['author_xchan']) && ($datarray['item_type'] == ITEM_TYPE_POST)) {
notification(array(
Zlib\Enotify::submit(array(
'type' => NOTIFY_WALL,
'from_xchan' => $datarray['author_xchan'],
'to_xchan' => $datarray['owner_xchan'],
@@ -978,10 +990,7 @@ class Item extends \Zotlabs\Web\Controller {
goaway(z_root() . "/" . $return_path );
// NOTREACHED
}
update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid);
if(($parent) && ($parent != $post_id)) {
// Store the comment signature information in case we need to relay to Diaspora
//$ditem = $datarray;
@@ -995,10 +1004,7 @@ class Item extends \Zotlabs\Web\Controller {
if($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
$rid = q("select * from item_id where iid = %d",
intval($post_id)
);
build_sync_packet($uid,array('item' => array(encode_item($sync_item[0],true)),'item_id' => $rid));
build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true))));
}
}
@@ -1008,15 +1014,10 @@ class Item extends \Zotlabs\Web\Controller {
call_hooks('post_local_end', $datarray);
if(! $nopush)
proc_run('php', 'include/notifier.php', $notify_type, $post_id);
\Zotlabs\Daemon\Master::Summon(array('Notifier', $notify_type, $post_id));
logger('post_complete');
// figure out how to return, depending on from whence we came
if($api_source)

View File

@@ -1,7 +1,7 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/channel.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
@@ -21,7 +21,7 @@ class Layouts extends \Zotlabs\Web\Controller {
else
return;
profile_load($a,$which);
profile_load($which);
}
@@ -90,13 +90,14 @@ class Layouts extends \Zotlabs\Web\Controller {
return;
}
//This feature is not exposed in redbasic ui since it is not clear why one would want to
//download a json encoded pdl file - we dont have a possibility to import it.
//Use the buildin share/install feature instead.
// This feature is not exposed in redbasic ui since it is not clear why one would want to
// download a json encoded pdl file - we dont have a possibility to import it.
// Use the buildin share/install feature instead.
if((argc() > 3) && (argv(2) === 'share') && (argv(3))) {
$r = q("select sid, service, mimetype, title, body from item_id
left join item on item.id = item_id.iid
where item_id.uid = %d and item.mid = '%s' and service = 'PDL' order by sid asc",
$r = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig
left join item on item.id = iconfig.iid
where uid = %d and mid = '%s' and iconfig.cat = 'system' and iconfig.k = 'PDL' order by iconfig.v asc",
intval($owner),
dbesc(argv(3))
);
@@ -141,8 +142,9 @@ class Layouts extends \Zotlabs\Web\Controller {
$editor = status_editor($a,$x);
$r = q("select iid, sid, mid, title, body, mimetype, created, edited, item_type from item_id left join item on item_id.iid = item.id
where item_id.uid = %d and service = 'PDL' and item_type = %d order by item.created desc",
$r = q("select iconfig.iid, iconfig.v, mid, title, body, mimetype, created, edited, item_type from iconfig
left join item on iconfig.iid = item.id
where uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' and item_type = %d order by item.created desc",
intval($owner),
intval(ITEM_TYPE_PDL)
);
@@ -164,7 +166,7 @@ class Layouts extends \Zotlabs\Web\Controller {
);
$pages[$rr['iid']][] = array(
'url' => $rr['iid'],
'title' => $rr['sid'],
'title' => $rr['v'],
'descr' => $rr['title'],
'mid' => $rr['mid'],
'created' => $rr['created'],

View File

@@ -264,23 +264,22 @@ class Like extends \Zotlabs\Web\Controller {
logger('like: no item ' . $item_id);
killme();
}
xchan_query($r,true,(($r[0]['uid'] == local_channel()) ? 0 : local_channel()));
$item = $r[0];
$owner_uid = $item['uid'];
$owner_aid = $item['aid'];
$sys = get_sys_channel();
// if this is a "discover" item, (item['uid'] is the sys channel),
// fallback to the item comment policy, which should've been
// respected when generating the conversation thread.
// Even if the activity is rejected by the item owner, it should still get attached
// to the local discover conversation on this site.
if(($owner_uid != $sys['channel_id']) && (! perm_is_allowed($owner_uid,$observer['xchan_hash'],'post_comments'))) {
$owner_uid = $r[0]['uid'];
$owner_aid = $r[0]['aid'];
$can_comment = false;
if((array_key_exists('owner',$item)) && intval($item['owner']['abook_self']))
$can_comment = perm_is_allowed($item['uid'],$observer['xchan_hash'],'post_comments');
else
$can_comment = can_comment_on_post($observer['xchan_hash'],$item);
if(! $can_comment) {
notice( t('Permission denied') . EOL);
killme();
}
@@ -346,7 +345,7 @@ class Like extends \Zotlabs\Web\Controller {
// drop_item was not done interactively, so we need to invoke the notifier
// in order to push the changes to connections
proc_run('php','include/notifier.php','drop',$rr['id']);
\Zotlabs\Daemon\Master::Summon(array('Notifier','drop',$rr['id']));
}
@@ -483,7 +482,7 @@ class Like extends \Zotlabs\Web\Controller {
$arr['verb'] = $activity;
$arr['obj_type'] = $objtype;
$arr['object'] = $object;
$arr['obj'] = $object;
if($target) {
$arr['tgt_type'] = $tgttype;
@@ -496,6 +495,8 @@ class Like extends \Zotlabs\Web\Controller {
$arr['deny_gid'] = $deny_gid;
$arr['item_private'] = $private;
call_hooks('post_local',$arr);
$post = item_store($arr);
$post_id = $post['item_id'];
@@ -531,7 +532,7 @@ class Like extends \Zotlabs\Web\Controller {
}
proc_run('php',"include/notifier.php","like","$post_id");
\Zotlabs\Daemon\Master::Summon(array('Notifier','like',$post_id));
if($interactive) {
notice( t('Action completed.') . EOL);

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