1352 Commits
1.0 ... 1.6

Author SHA1 Message Date
redmatrix
ac1ec99684 Merge branch 'dev' 2016-05-11 20:20:17 -07:00
redmatrix
8e5718bf04 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-11 20:18:42 -07:00
redmatrix
89561bec4f move dev pointer past current release 2016-05-11 20:18:11 -07:00
redmatrix
fae78b947f push point release 2016-05-11 20:16:57 -07:00
redmatrix
d35dfc12ce Merge pull request #377 from anaqreon/chat-notify
Chat browser notifications
2016-05-12 11:39:41 +10:00
redmatrix
69112a17ac Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-11 17:27:48 -07:00
redmatrix
32ad8bbaac Ensure that channels can't be created with DAV reserved paths as a redress. Sabre mentions in several places that trying to change these paths to other strings; while possible - is unsupported and likely to cause problems. So for now, we're stuck with 'principals', 'addressbooks', and 'calendars'. If you already have these redresses on your site, you're basically buggered. 2016-05-11 17:18:17 -07:00
Andrew Manning
913d07a4a7 Merge remote-tracking branch 'upstream/dev' into chat-notify 2016-05-11 20:08:54 -04:00
Andrew Manning
b40d8070f3 Browser notification issued when member enters chat room 2016-05-11 20:02:19 -04:00
redmatrix
1fb21b781f Merge pull request #376 from anaqreon/plugin-repo
Check if target directories are writable when adding, updating, or removing plugin repos
2016-05-12 08:57:22 +10:00
Mario Vavti
25df2080ea more whitespace 2016-05-11 22:31:05 +02:00
Mario Vavti
5632022d79 whitespace 2016-05-11 22:23:13 +02:00
Andrew Manning
d968fc51ea Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-11 05:54:20 -04:00
Andrew Manning
c7698e4dc3 Check if target directories are writable when adding, updating, or removing plugin repos 2016-05-11 05:53:23 -04:00
redmatrix
4dd3839c41 provide repository versions on admin summary page and an upgrade message if you're behind master 2016-05-10 21:46:04 -07:00
redmatrix
9caaa9397e Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-10 19:42:37 -07:00
redmatrix
915bd2ec77 sabre upgrade 2016-05-10 19:40:15 -07:00
redmatrix
ba64b11ac0 Merge pull request #375 from anaqreon/plugin-repo
Plugin repo
2016-05-11 11:07:35 +10:00
Andrew Manning
40e3d37a72 Remove debugging lines 2016-05-10 21:01:47 -04:00
Andrew Manning
2882eef42f Link plugins in the newly installed addon repo to /addon so they are accessible 2016-05-10 21:00:10 -04:00
redmatrix
0b02a6d123 initial sabre upgrade (needs lots of work - to wit: authentication, redo the browser interface, and rework event export/import) 2016-05-10 17:26:44 -07:00
redmatrix
40b5b6e9d2 Merge pull request #374 from anaqreon/plugin-repo
Delete existing repo if the new one has a different URL. Fixed bug th…
2016-05-10 21:11:35 +10:00
Andrew Manning
78b40e6363 Delete existing repo if the new one has a different URL. Fixed bug that could cause repeated installation. 2016-05-10 06:28:00 -04:00
Mario Vavti
45c19e365d another public -> pubstream 2016-05-10 10:40:36 +02:00
redmatrix
2469853175 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-10 01:31:15 -07:00
redmatrix
0c5434d5e3 try again with shutdown handler, fix issue #373 (live-pubstream div wasn't present 2016-05-10 01:30:22 -07:00
Mario Vavti
8ab7707898 allow delayed publishing of webpages 2016-05-10 10:02:27 +02:00
redmatrix
baa7020036 revert shutdown function 2016-05-09 22:28:54 -07:00
redmatrix
f658a3cae1 more work on diaspora relay 2016-05-09 20:17:59 -07:00
redmatrix
a674b05e96 register shutdown procedure 2016-05-09 19:13:27 -07:00
redmatrix
b7e7ef0bf3 Merge pull request #372 from anaqreon/plugin-repo
Manage addon git repositories via the admin plugins page
2016-05-10 12:12:20 +10:00
Andrew Manning
0b8a7f1bd0 Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-09 22:00:21 -04:00
Andrew Manning
9c8cf7d433 Fixed some bugs with empty repo name and improved the interface a bit. 2016-05-09 21:59:27 -04:00
Andrew Manning
180731c162 copy-paste error 2016-05-09 21:17:47 -04:00
redmatrix
ea1173f8f6 Merge pull request #371 from Treer/permissions
minor cleanup. No functional changes
2016-05-10 06:13:05 +10:00
Treer
ef97e5a063 minor cleanup. No functional changes 2016-05-10 00:15:57 +10:00
Mario Vavti
61909d2480 if we do not have a layout $layout should be empty not default 2016-05-09 12:24:48 +02:00
Mario Vavti
7aeff7505b remove unused code and whitespace 2016-05-09 12:09:04 +02:00
Mario Vavti
a3e94591bc Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-05-09 11:58:10 +02:00
Mario Vavti
24c1dc528d make editwebpage use status_editor() and fix storing of layout on webpage creation 2016-05-09 11:56:42 +02:00
redmatrix
6f486a3393 prevent recursion in the database driver when debugging is enabled and the system config is not yet loaded - caused by calling get_config and making db calls within the logger function; which we then attempt to log... 2016-05-09 01:12:24 -07:00
Mario Vavti
c8f686b8a5 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-05-09 09:26:38 +02:00
redmatrix
94accd8a4c remove the old IE html5 hack. 2016-05-08 20:25:10 -07:00
redmatrix
b6e0d8dee0 clean up some cruft 2016-05-08 20:19:23 -07:00
redmatrix
2a14c71128 convert media embed functions that deal with rewriting specific corporate services to addon hooks 2016-05-08 19:12:52 -07:00
Andrew Manning
d714cd76dd Addon repo is copied to /extend/addon/ when admin presses install. Addon repos can be removed via GUI. 2016-05-08 20:30:00 -04:00
redmatrix
5ac262bd61 Merge pull request #370 from Treer/permissions
ACL dialogs: Make the non-ACL-option description more accurate
2016-05-09 06:53:31 +10:00
Andrew Manning
174484a51c Custom addon repo name option added. 2016-05-08 09:26:06 -04:00
Treer
09ef30feb0 Update some modules to use new ACL dialog feature 2016-05-08 21:27:52 +10:00
Treer
e7a65c1f8d improve non-ACL option description in ACL dialog 2016-05-08 20:44:30 +10:00
Andrew Manning
f73a74967e Existing addon repos are listed on plugin page with controls for updating, removing, and switching branches. 2016-05-07 22:12:12 -04:00
Andrew Manning
bbbae3f42d Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-07 18:39:34 -04:00
Andrew Manning
0746794e81 New plugin repo cloned using new GitRepo class. Readme and info displayed in wide modal dialog. 2016-05-07 18:39:19 -04:00
redmatrix
2b77c9a74b SDAV is already absolute 2016-05-07 14:23:38 -07:00
Mario Vavti
75128e8f68 make editblock use status_editor() 2016-05-07 23:05:48 +02:00
Andrew Manning
284d86ad76 Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-07 16:22:35 -04:00
Andrew Manning
852ff39856 Progress implementing GitRepo class in Zotlabs/Storage 2016-05-07 16:21:52 -04:00
git-marijus
7f974a543f Merge pull request #369 from Treer/fontawesome
update two Font Awesome icons
2016-05-06 21:43:59 +02:00
Andrew Manning
6950100ff4 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into plugin-repo 2016-05-06 13:42:22 -04:00
Treer
e9e2159b3b update 2 fontawesome icons 2016-05-06 23:37:12 +10:00
Mario Vavti
b08fc746d8 use section-content-info-wrapper class for info text 2016-05-06 10:55:11 +02:00
Mario Vavti
4a36834d3f use darker background colour only for searchbar 2016-05-06 10:42:38 +02:00
redmatrix
5882714e23 missed one other place where we called comanche outside the page build 2016-05-06 00:43:37 -07:00
redmatrix
7101bbedcb objectify comanche 2016-05-05 23:07:35 -07:00
redmatrix
712b2b1bb2 comments 2016-05-05 22:02:46 -07:00
Andrew Manning
3011d3768c Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-05 21:49:24 -04:00
redmatrix
5508feb6ce Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-05 18:19:20 -07:00
redmatrix
2e3da0cbbb - Setup: check php version (5.4 required)
- Comanche: implement conditionals. Currently the only supported tests are true/false for system config settings
and supports the following forms:

[if $config.system.foo]
[widget=widget1][/widget]
[else]
[widget=widget2][/widget]
[/if]

[if $config.system.foo]
[widget=widget1][/widget]
[/if]
2016-05-05 18:15:07 -07:00
redmatrix
f38c8e5eca Merge pull request #368 from Treer/permissions
Unify permissions dialog for network posts, channel posts, and remote posts
2016-05-06 08:54:55 +10:00
Treer
2174cdcd0e Unify permissions dialog for network posts, channel posts, and remote posts
* changes the warning from being about when a post is "sent" to when it's "shared", to match the Share button.
* hyperlinks the "cannot be changed" part of the warning to the help file
* adds some more content to the help file
2016-05-06 01:44:46 +10:00
Andrew Manning
6ce939491b Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-05 05:35:00 -04:00
redmatrix
8ffdc4859b replace app tagcloud with more traditional categories widget. One can always change this in the PDL 2016-05-05 00:45:38 -07:00
redmatrix
9b19a51fc6 Allow follow to work with a pasted webbie from the profile page (where we've replaced the '@' sign with a UTF-8 look-alike) 2016-05-04 20:24:47 -07:00
redmatrix
9eac9ef2b9 isolate all the tagadelic core code into a class and reuse it 2016-05-04 19:39:39 -07:00
redmatrix
566667a263 provide a tag cloud for app categories and allow filtering apps from this 2016-05-04 18:27:46 -07:00
Andrew Manning
8cb06e7af8 Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-04 21:26:52 -04:00
redmatrix
1b6bc5394b Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-04 17:36:13 -07:00
redmatrix
50fb525b28 add categories to apps (wip) 2016-05-04 17:35:27 -07:00
redmatrix
8c9a773a90 Merge pull request #366 from Treer/permissions
Refining the Permission settings dialog
2016-05-05 06:29:30 +10:00
Treer
e1e56936c9 add help to some permissions dialogs 2016-05-05 02:09:47 +10:00
Treer
33a8d845c1 Refine permissions dialog UI 2016-05-04 23:55:32 +10:00
Mario Vavti
9fe33bb67d whitespace 2016-05-04 11:53:38 +02:00
Mario Vavti
0db8d3f6c6 whitespace 2016-05-04 11:49:29 +02:00
redmatrix
7c57da3a28 Sync the current list of system apps with the built-in name translation table. Some of the names were changed in the past without the translation table being updated to reflect it. 2016-05-03 22:12:09 -07:00
redmatrix
1685548a4c ensure that important system fields are passed through the appman editor 2016-05-03 21:59:26 -07:00
redmatrix
191298ec93 more background work for app management - give every member a copy of all the system apps so that they can edit and delete them to taste/preference. This needs further work to pick up changes in system apps (additions, edits, deletions, etc.). Currently this is done once and never attempted again. 2016-05-03 20:37:05 -07:00
Andrew Manning
e4a2aacd1d Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-03 21:50:34 -04:00
Andrew Manning
5686ee13b4 Increased PHPGit timeout to 120 seconds for large repos. Retrieve Readme.md and render on plugins page. 2016-05-03 21:49:52 -04:00
redmatrix
45c7a03a0d Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-03 18:42:06 -07:00
redmatrix
3df0bb5522 some preliminary structural work for app organisation 2016-05-03 18:41:16 -07:00
git-marijus
7fe697d896 Merge pull request #365 from Treer/fontawesome
another font-awesome icon
2016-05-03 20:51:16 +02:00
Treer
0bdcaff00f another font-awesome icon 2016-05-04 00:32:08 +10:00
Andrew Manning
2db86b950e Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-03 06:33:11 -04:00
Andrew Manning
9619d02be9 AJAX and spinner for add repo form submission. Repo info will be displayed below the form. 2016-05-03 06:30:46 -04:00
redmatrix
dccdeedb75 add the new hook 2016-05-02 22:30:57 -07:00
redmatrix
b371c028ad more security stuff 2016-05-02 22:28:27 -07:00
redmatrix
b017f8f2ab Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-02 13:32:04 -07:00
redmatrix
2b7b26f4c0 a bit more oembed security - and document the shortcomings of this approach 2016-05-02 13:31:14 -07:00
redmatrix
ae39217a7e Merge pull request #364 from mjfriaza/dev
Contextual help in Spanish
2016-05-03 06:03:15 +10:00
Manuel Jiménez Friaza
78e42a75f1 Contextual help in Spanish 2016-05-02 14:00:13 +02:00
redmatrix
559ed3f0a8 sort out the rest of the source categories 2016-05-02 01:18:18 -07:00
redmatrix
a10fe5f13e a couple of bugfixes from earlier checkins and implementation of source tags 2016-05-01 22:45:38 -07:00
redmatrix
bd2f11ed8b db schema change to add tags to content sources 2016-05-01 21:00:02 -07:00
redmatrix
5e458491f1 sort addons based on the internal display name instead of the filename 2016-05-01 20:43:57 -07:00
Andrew Manning
4ed5d6573c Merge remote-tracking branch 'upstream/dev' into plugin-repo 2016-05-01 22:31:02 -04:00
Andrew Manning
c2d15e6c3b New plugin repo is cloned to /store/pluginrepos/REPONAME for analysis 2016-05-01 22:29:51 -04:00
redmatrix
f284558007 use only the std_version 2016-05-01 19:29:30 -07:00
redmatrix
23bb4e8e15 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-05-01 19:20:09 -07:00
redmatrix
cd518625bf some much needed work on oembed security 2016-05-01 19:19:17 -07:00
Andrew Manning
b1ae4d776c fixed tpl 2016-05-01 21:25:15 -04:00
Andrew Manning
95b9669213 Create form on admin/plugins page to add plugin git repo using PHPGit 2016-05-01 21:20:49 -04:00
Mario Vavti
b4bf71dd06 fix mime-type icons in /cloud 2016-05-01 16:34:55 +02:00
Mario Vavti
b35e69273d tweak dl bbcode in expanded autocomplete a bit more 2016-05-01 16:17:34 +02:00
git-marijus
4560298b98 Merge pull request #363 from Treer/bbcode
tweak dl bbcode in expanded autocomplete
2016-05-01 15:50:11 +02:00
Mario Vavti
d892a47ac9 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-05-01 15:45:57 +02:00
Mario Vavti
fa80a5c113 make weblink and attach button hideable and some minor fixes 2016-05-01 15:45:42 +02:00
Mario Vavti
7fac859fbd css fix 2016-05-01 12:16:42 +02:00
Treer
02d8363019 tweak dl bbcode in expanded autocomplete 2016-05-01 16:03:36 +10:00
redmatrix
84d93cca6e Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-30 15:02:45 -07:00
redmatrix
9446d0cbb4 Merge pull request #362 from Treer/fontawesome
Update Font-Awesome to 4.6.1
2016-05-01 08:02:03 +10:00
Mario Vavti
8a41e2a011 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-04-30 23:38:40 +02:00
Mario Vavti
36fe2ac87e css fix 2016-04-30 23:38:25 +02:00
Treer
3fe8fc0aa8 update icon names in library 2016-05-01 06:48:18 +10:00
jeroenpraat
3d9fcee075 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-04-30 22:30:37 +02:00
jeroenpraat
917bcb55fd Small fix of Dutch strings 2016-04-30 22:29:59 +02:00
Mario Vavti
026787fc73 whitespace 2016-04-30 22:26:45 +02:00
Mario Vavti
d43c7603bf more work on layout editors 2016-04-30 22:21:00 +02:00
Treer
17dba9542a update icon names in view/ 2016-05-01 05:59:02 +10:00
Mario Vavti
c96b20c559 make mod editlayout use status_editor() 2016-04-30 21:56:52 +02:00
Mario Vavti
8189a7c693 add dl bbcode to the expanded autocomplete 2016-04-30 21:19:43 +02:00
Treer
2f74f9eb40 update icon names in view/js 2016-05-01 04:51:01 +10:00
Mario Vavti
ab17b2e0d6 minor cleanup 2016-04-30 20:47:52 +02:00
Treer
8f16e9ad33 update icon names in include/ 2016-05-01 04:39:57 +10:00
Treer
7d380570df update icon names in Zotlabs/ 2016-05-01 04:13:30 +10:00
git-marijus
80c9a8b8f6 Merge pull request #361 from Treer/bbcode
Add definition lists to bbcode
2016-04-30 19:24:43 +02:00
jeroenpraat
8544819be1 Update NL+ES-ES 2016-04-30 14:13:16 +02:00
Treer
45654ffc5c update font-awesome library to 4.6.1
Perhaps this should be done as a submodule instead?
2016-04-30 21:36:19 +10:00
redmatrix
45512e6aba Merge branch 'master' into dev 2016-04-29 23:50:05 -07:00
redmatrix
d7a64845fe version+strings 2016-04-29 23:48:36 -07:00
redmatrix
4c47d22f4b trim engr_units string slight improvement to avoid subtle bugs 2016-04-29 23:47:13 -07:00
Mario Vavti
931a4fafe3 get rid of the unused ispublic variable 2016-04-29 21:38:36 +02:00
Mario Vavti
83a0e82d5c css fix 2016-04-29 20:01:54 +02:00
Treer
e7fbf1b017 clean up some doc/ formatting 2016-04-30 02:42:28 +10:00
Treer
b5b21ecad7 improve whitespace control around definition list ([dl]) bbcode 2016-04-30 02:03:38 +10:00
Treer
9d079e5d2b Add definition lists to bbcode 2016-04-30 01:13:34 +10:00
git-marijus
18f505608b Merge pull request #360 from sasiflo/dev_sasiflo_contexthelp
context help: added german translation
2016-04-29 14:32:50 +02:00
Mario Vavti
b797528b78 some work on making mod editpost use status_editor() - if you find anything related to jot broken please revert this commit 2016-04-29 13:18:42 +02:00
sasiflo
d8aa0ac36c Merge branch 'dev' into dev_sasiflo_contexthelp 2016-04-29 11:40:38 +02:00
sasiflo
49b957f7ea Added german translation to context help. 2016-04-29 11:39:00 +02:00
Mario Vavti
e01b90c4c6 css fixes 2016-04-29 10:26:41 +02:00
Mario Vavti
1fdac57d61 jot: cleanup unused variables 2016-04-29 09:58:44 +02:00
redmatrix
bb96f44861 allow engineering units (e.g. 400M, 1G) as service class limits 2016-04-28 21:02:27 -07:00
redmatrix
30a6ae3daa This setting isn't implemented so remove the UI until it is. 2016-04-28 20:17:05 -07:00
redmatrix
37a852d2d1 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-28 18:29:37 -07:00
redmatrix
59777333dd Merge branch 'master' into dev 2016-04-28 18:29:27 -07:00
redmatrix
eb85f8572f revup 2016-04-28 18:27:58 -07:00
Mario Vavti
b664af748e provide help button in context help popup 2016-04-28 13:08:41 +02:00
Mario Vavti
f108838ca9 css fix 2016-04-28 11:42:37 +02:00
redmatrix
2ddd03f597 provide a Hook method to unregister all hooks with a given filespec component. This will be useful in upgrading plugins to use new interfaces, as you won't have to individually unregister hook declarations that you are no longer using in the code. 2016-04-27 22:44:06 -07:00
redmatrix
bdef71bda0 provide courtesy function for syncing one item. We'll probably be doing this a lot. 2016-04-27 21:26:52 -07:00
redmatrix
d4eb5e7c6d Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-27 13:27:19 -07:00
redmatrix
8e8df26066 Use / for album name in photo activities if no album present. 2016-04-27 13:25:58 -07:00
redmatrix
c91e43af34 Merge pull request #359 from anaqreon/help-content
Help content
2016-04-28 06:18:11 +10:00
Andrew Manning
b13c21f872 Added context help content 2016-04-27 06:23:05 -04:00
Andrew Manning
f975d9dfe4 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into help-content 2016-04-27 05:56:19 -04:00
Mario Vavti
a6baa5a6da some refinements on jot 2016-04-27 11:36:02 +02:00
redmatrix
26131ffc91 Merge branch 'master' into dev 2016-04-27 00:53:05 -07:00
redmatrix
aeda293bd0 revup 2016-04-27 00:52:00 -07:00
redmatrix
a67fa2651d implement the singleton delivery stuff 2016-04-26 17:38:44 -07:00
redmatrix
509f25e46a Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-26 16:14:10 -07:00
redmatrix
f99daf8ff9 move iconfig functions to include/config.php with all the rest of the configs, fix an issue with singleton discovery and start work on singleton delivery 2016-04-26 16:12:31 -07:00
Mario Vavti
607125e795 only padding-top needs adjustment 2016-04-26 16:15:29 +02:00
Mario Vavti
f34dcffbd9 hopefully fix jot dropdown visibility issue 2016-04-26 13:45:39 +02:00
Mario Vavti
ce50a429fa Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-04-26 11:41:23 +02:00
Mario Vavti
3446e68ac2 move spoiler= and quote= bbcode handling from prepare_body() to bbcode() and add open tag to bbco_autocomplete 2016-04-26 11:41:08 +02:00
redmatrix
e508ad37c1 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-26 01:07:52 -07:00
redmatrix
f55d9e8c62 Merge branch 'master' into dev 2016-04-26 01:07:40 -07:00
redmatrix
563e82feff revup 2016-04-26 01:06:25 -07:00
Mario Vavti
5553df862a fix top padding for narrow navbar 2016-04-26 09:49:54 +02:00
redmatrix
2e7028c976 some cleanup on the mysqli driver 2016-04-25 22:03:02 -07:00
redmatrix
78e4b64c8b Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-25 20:14:07 -07:00
redmatrix
d62f490814 Setup was horked after this commit and I couldn't easily make it right so reverting - will try again at a future date
Revert "remove global db variable"

This reverts commit c3b0c0f32a.
2016-04-25 20:12:36 -07:00
redmatrix
6bf7716518 Revert "Revert "revert inline-block for blockquote""
This reverts commit ae02624793.
2016-04-25 20:11:36 -07:00
redmatrix
ae02624793 Revert "revert inline-block for blockquote"
This reverts commit 15cfd6fda7.
2016-04-25 20:10:16 -07:00
redmatrix
c3b0c0f32a remove global db variable 2016-04-25 16:55:33 -07:00
redmatrix
6aef5593d5 Merge pull request #356 from Treer/CUI
extends util/config and util/pconfig
2016-04-26 06:19:41 +10:00
jeroenpraat
975140634c +es-es strings update 2016-04-25 15:15:24 +02:00
Treer
f336f38ad5 improve error message in config and pconfig 2016-04-25 22:09:15 +10:00
Andrew Manning
f027bf81cd Merge remote-tracking branch 'upstream/dev' into help-content 2016-04-25 06:17:39 -04:00
Treer
d67d8b6d6e util/pconfig can list channel IDs 2016-04-25 19:46:04 +10:00
Treer
02ee7f17e8 add commandline help to util/pconfig 2016-04-25 19:30:37 +10:00
Treer
78320ee3a6 add commandline help to util/config 2016-04-25 19:00:10 +10:00
Mario Vavti
a9d926886e make it more obvious what is behind the dropdowns 2016-04-25 10:00:50 +02:00
redmatrix
6291c08e01 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-25 00:10:13 -07:00
redmatrix
4b9c3cc998 Merge branch 'master' into dev 2016-04-25 00:09:55 -07:00
redmatrix
fdf7120aec revup 2016-04-25 00:08:42 -07:00
redmatrix
e5e68d7350 Merge pull request #355 from Treer/document_tweaks
Document tweaks
2016-04-25 08:10:21 +10:00
Treer
d914290002 merged duplicate entry in docs 2016-04-25 03:17:48 +10:00
Treer
42ee3ab21c add default_photo_profile to docs 2016-04-25 03:09:52 +10:00
Mario Vavti
15cfd6fda7 revert inline-block for blockquote 2016-04-24 12:45:38 +02:00
redmatrix
0e34811886 add some missing hook entries to the doco 2016-04-23 22:55:45 -07:00
redmatrix
5b3f536613 updated doco to document how to use hook callbacks which are object methods 2016-04-23 17:47:00 -07:00
redmatrix
ce45a1cf94 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-23 16:57:32 -07:00
redmatrix
79c63e3cf4 this should work to call a hook for a string class method 2016-04-23 16:56:41 -07:00
redmatrix
df2990b27e Class method support for hooks 2016-04-23 15:16:54 -07:00
Mario Vavti
9d698c0887 fix context help position with narrow navbar 2016-04-23 23:52:39 +02:00
Mario Vavti
1e27038b73 update jquery.textcomplete to version 1.3.4 and add minified version 2016-04-23 21:42:10 +02:00
Mario Vavti
7e30c1dd82 update smarty to version 3.1.29 2016-04-23 21:24:22 +02:00
Mario Vavti
78bf4564f2 make the link to /help in dropdown conditional to the use of context help 2016-04-23 17:22:39 +02:00
Mario Vavti
665a517a47 bump std version to prevent issues with context help js changes 2016-04-23 16:55:55 +02:00
Mario Vavti
57110cbe76 pull-right is not needed here 2016-04-23 16:52:02 +02:00
Mario Vavti
b0a2e5d3f7 simplify context help js and move it to main.js where all the nav related js resides, do not close the context help if we click outside of it - members might want to work on something while help is open, move the link to /help to dropdown-menu. 2016-04-23 16:39:56 +02:00
Andrew Manning
f3eae7132f Merge branch 'dev' of https://github.com/redmatrix/hubzilla into help-content 2016-04-23 07:36:06 -04:00
Mario Vavti
0463df62f0 only display help button in collapsed panel if context help is enabled 2016-04-23 13:21:25 +02:00
redmatrix
a8823ae7d8 Merge branch 'master' into dev 2016-04-23 00:06:30 -07:00
redmatrix
fdef224da1 Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-04-23 00:05:33 -07:00
redmatrix
59c642ed19 revup 2016-04-23 00:05:12 -07:00
redmatrix
2b91962b32 Merge pull request #352 from phellmes/de20160422
Update DE translation strings
2016-04-23 07:46:44 +10:00
phellmes
61e695e143 Update DE translation strings 2016-04-22 20:00:14 +02:00
Andrew Manning
aab9218558 Added help content 2016-04-22 11:50:46 -04:00
redmatrix
c250cb955e Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-22 00:51:49 -07:00
redmatrix
f111275ddf Merge branch 'master' into dev 2016-04-22 00:51:32 -07:00
redmatrix
2726c68b60 revup 2016-04-22 00:50:42 -07:00
redmatrix
1288a72963 more doco 2016-04-22 00:50:19 -07:00
Mario Vavti
d66f6c8e8c make it icon-question-sign for contextual and icon-question for normal help instead of adding a caret-down 2016-04-22 09:16:17 +02:00
redmatrix
a3ce194bf5 Some issues discovered with linkinfo module, and update the doco about using object modules in addons; as there were a couple of surprises. 2016-04-21 22:16:57 -07:00
redmatrix
5a427dcee3 No idea how long RSD (Really Simple Discovery) has been broken. I had no idea it was even here. 2016-04-21 20:14:55 -07:00
redmatrix
7d45f63b78 updated help/plugins to reflect some of the new interfaces and procedures 2016-04-21 17:53:56 -07:00
redmatrix
540800da95 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-21 17:09:13 -07:00
redmatrix
1ff189ee90 new hook interface (the old one still works but requires handlers to have two calling arguments; the first of which is no longer used). The new interface is called from Zotlabs\Extend\Hook::register() and allows you to specify which hook version to use. The default will be the new interface with one function argument. We also implement the hook priority field which was always there but needed to be set manually in the DB. This provides a way for two hook handlers that implement the same hook interface to determine which order to be called in the event of conflicts. 2016-04-21 17:03:05 -07:00
redmatrix
692e41c41e provide a way for the router to support custom controller objects and allow plugins to register class objects as modules instead of the traditional procedural interface. 2016-04-21 16:09:25 -07:00
Mario Vavti
cb8c83a42b remove obsolete class 2016-04-21 23:56:53 +02:00
Mario Vavti
bd11b1d61a indicate if we will be displayed contextual help or default help 2016-04-21 23:55:38 +02:00
Mario Vavti
96d19c09f3 fix help button for collapsed state 2016-04-21 23:19:17 +02:00
Mario Vavti
d7f4bfedd5 some fixes for contextual help and disable transition animation for now - it looked really wired because main moved with a different speed than help-content and help-content can not be displayed under the panel as it is implemented now. 2016-04-21 23:03:09 +02:00
git-marijus
391ed8655e Merge pull request #351 from anaqreon/toggle-context-help
Toggle context help
2016-04-21 18:44:50 +02:00
git-marijus
aa0c70e198 Merge pull request #348 from git-marijus/dev
add querystring to css and js which is added via head_add_{css, js}
2016-04-21 18:42:49 +02:00
Andrew Manning
82de68c3d3 Added admin/site setting that toggles context help panel. If disabled, original help menu button behavior is restored. 2016-04-21 06:41:55 -04:00
redmatrix
4669107634 Merge branch 'master' into dev 2016-04-21 01:08:38 -07:00
redmatrix
cf79c4ea48 Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-04-21 01:08:00 -07:00
redmatrix
ae932922c4 revup #337 2016-04-21 01:07:46 -07:00
git-marijus
bacd05ea9e Merge pull request #349 from HaakonME/master
Updated Hubzilla on OpenShift deploy script to include unofficial repos
2016-04-21 09:14:32 +02:00
redmatrix
657b34c012 change the 404 warning from the router to reflect the new architecture 2016-04-20 22:50:59 -07:00
redmatrix
5eb594706b make the cookie check agnostic to cookie state 2016-04-20 22:17:02 -07:00
redmatrix
2b0a04ea9e revert the reversal of checkjs logic, but still restrict the behaviour scope to just those urls that require it 2016-04-20 22:10:00 -07:00
redmatrix
f00a701ad1 send the correct number of args 2016-04-20 19:56:01 -07:00
redmatrix
dff9e18c1e We no longer require the diaspora_meta service locally. 2016-04-20 19:54:26 -07:00
redmatrix
d2f67bf249 Merge branch 'dmeta' into dev
several diaspora changes/fixes
2016-04-20 19:06:36 -07:00
redmatrix
8f64b28fb9 upgrade std rev 2016-04-20 19:06:19 -07:00
redmatrix
0d91f363cc There is no longer a followup flag in the notifier. Remove all traces of it. 2016-04-20 19:03:56 -07:00
redmatrix
23180ae078 Merge branch 'dev' into dmeta 2016-04-20 18:16:15 -07:00
Andrew Manning
b96eb1c823 Merge branch 'dev' into toggle-context-help 2016-04-20 21:05:01 -04:00
redmatrix
635580091a Merge branch 'master' into dev 2016-04-20 17:43:20 -07:00
redmatrix
a768bb1ab2 Merge branch 'master' into dev 2016-04-20 17:41:51 -07:00
Mario Vavti
59799ba2b4 some crossbrowser rendering work on the comment box 2016-04-20 21:59:29 +02:00
Mario Vavti
8147e6203f Use stopImmidiatePropagation() only if we are in a list to not interfere with other keypress listeners (e.g. chat). 2016-04-20 14:13:09 +02:00
redmatrix
2641980ac2 bb2d updates from testing signature changes 2016-04-20 01:40:09 -07:00
redmatrix
683da1aa77 revup #337 2016-04-20 01:19:13 -07:00
redmatrix
21b0128e9e testing dmeta 2016-04-19 23:06:43 -07:00
redmatrix
d07afb54e4 rework bb2diaspora for eradicating the diaspora comment virus 2016-04-19 21:43:12 -07:00
redmatrix
1e8b3fe749 Revert the last edit on this file. Need to work this through a bit more before changing this bit. 2016-04-19 20:02:55 -07:00
redmatrix
9040ee53e4 missing class instance pointer in Pconfig module upgrade 2016-04-19 19:09:35 -07:00
redmatrix
974390d5d2 remove test files which were committed by accident 2016-04-19 19:02:48 -07:00
redmatrix
8a57b845ae second phase of diaspora comment virus eradication begins 2016-04-19 17:03:14 -07:00
redmatrix
324771f858 Merge branch 'master' into dev 2016-04-19 15:51:41 -07:00
redmatrix
dd7fdf0c2b Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-04-19 13:04:59 -07:00
redmatrix
bb7b756974 revup #337 2016-04-19 13:04:44 -07:00
Haakon Meland Eriksen
e805f589aa Updated Hubzilla on OpenShift deploy script to include unofficial repos by appending the 'insecure' argument 2016-04-19 19:23:40 +02:00
Mario Vavti
6941fbb182 add querystring to css and js which is added via head_add_{css, js} 2016-04-19 13:38:06 +02:00
Andrew Manning
7594796ee1 Try toggling context help using onclick attribute 2016-04-19 05:52:16 -04:00
redmatrix
f53478f142 a bit more namespace wrangling 2016-04-18 20:47:11 -07:00
redmatrix
2a4e8972e0 module updates 2016-04-18 20:38:38 -07:00
redmatrix
2a61817bad Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-18 19:17:20 -07:00
Haakon Meland Eriksen
e47a473e2c Merge remote-tracking branch 'upstream/master' 2016-04-18 18:07:20 +02:00
Mario Vavti
094d4cc325 Merge branch 'master' into dev 2016-04-18 16:45:58 +02:00
Mario Vavti
a49fa5f87c bring back bbcode buttons for mod/editpost 2016-04-18 16:45:34 +02:00
Mario Vavti
ca59ecd107 Merge branch 'master' into dev 2016-04-18 10:57:20 +02:00
Mario Vavti
f761ea5fc9 fix rpost bbcode buttons and autocomplete 2016-04-18 10:56:51 +02:00
redmatrix
1698732cff convert all the _well_known service controllers which are a bit touchy when it comes to the router 2016-04-18 01:35:09 -07:00
redmatrix
a9f68e4d2a Merge branch 'master' into dev 2016-04-18 01:02:44 -07:00
redmatrix
f12af17238 revup #337 2016-04-18 01:02:03 -07:00
redmatrix
d1ecf3f323 some issues with GNU-Social's implementation of events in feeds. The summary element is over-riding content, so put summary into the xcal namespace. Some investigation reveals that both projects are non-compliant in the xcal space. Will deal with this later. 2016-04-18 00:59:42 -07:00
redmatrix
9cddbc9a47 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-17 19:58:59 -07:00
redmatrix
966773cdbb pull in the new object router and a few selected samples for the new controller layout 2016-04-17 19:55:36 -07:00
redmatrix
d2e61122c5 Merge commit '521d404' into dev 2016-04-17 19:42:43 -07:00
jeroenpraat
7229cd56ed Making sure the great new context help works with all thmes and schema's (3rd party themes: maybe abit of tweaking is still needed). Also fixing some minor cosmetic things. 2016-04-18 01:57:54 +02:00
redmatrix
521d404013 remove the date hack on public feeds which was a temporary fix for an issue limiting the number of posts returned and no longer needed. 2016-04-17 16:37:44 -07:00
redmatrix
5591eac973 Merge pull request #345 from anaqreon/context-help
New help panel that slides in from the top and pushes the content ...
2016-04-18 06:47:57 +10:00
jeroenpraat
c8dec1fae5 Spanish and Dutch strings update 2016-04-17 19:27:40 +02:00
redmatrix
c366bbaa54 Merge branch 'master' into dev 2016-04-17 04:31:20 -07:00
redmatrix
72e7c50968 revup #337 2016-04-17 04:29:50 -07:00
Andrew Manning
f4cca21fdf Recover lost language translation accommodation and doc/context restructuring 2016-04-17 07:29:08 -04:00
Andrew Manning
d7fe48d1b6 New help panel that slides in from the top and pushes the content down so it is not covered. Panel toggles with help button. Still some bugs with small screen viewing. 2016-04-17 07:09:42 -04:00
Haakon Meland Eriksen
fddacf0a5a Merge remote-tracking branch 'upstream/master' 2016-04-16 15:18:31 +02:00
redmatrix
08a651dc9d Merge branch 'master' into dev 2016-04-16 00:39:29 -07:00
redmatrix
65571249b2 revup #337 2016-04-16 00:38:45 -07:00
Haakon Meland Eriksen
b4205554a8 Commented out extra repos except official addons 2016-04-16 09:29:31 +02:00
redmatrix
0865d0ef51 Convert Channel to new module 2016-04-15 22:36:07 -07:00
redmatrix
b57f69d14d cleanup and test of new router 2016-04-15 20:43:05 -07:00
redmatrix
07650b4646 get init() working with class modules 2016-04-15 16:13:55 -07:00
redmatrix
ce582ccada Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-15 14:27:44 -07:00
redmatrix
ee5163ce64 Merge branch 'master' into dev 2016-04-15 14:27:28 -07:00
Mario Vavti
bbe33f9503 Merge branch 'master' into dev 2016-04-15 12:42:12 +02:00
Mario Vavti
2cb04ccb8f nav: move js and css out of template, provide a help button in the panel on small screens and lots of whitespace cleanup 2016-04-15 12:39:22 +02:00
redmatrix
aaa327ca05 testing the new router/module code 2016-04-15 01:25:15 -07:00
Mario Vavti
ce34c4086d Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-04-15 09:53:34 +02:00
Mario Vavti
fe9df64fc2 fix some slight crossbrowser rendering issues with jot 2016-04-15 09:52:40 +02:00
redmatrix
f124f4a9f5 Merge branch 'master' into dev 2016-04-15 00:49:17 -07:00
redmatrix
a1af2cbb30 Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-04-15 00:48:38 -07:00
redmatrix
ec9e914798 revup + strings #337 2016-04-15 00:48:18 -07:00
Wave
ec5bd9d679 Merge pull request #343 from wave72/master
Updated Italian strings
2016-04-15 09:31:38 +02:00
Paolo Tacconi
c38c79d71c Merge branch 'redmatrix-master' 2016-04-15 09:22:27 +02:00
Paolo Tacconi
45a854762b Resolved conflict in view/it/hstrings.php 2016-04-15 09:20:58 +02:00
Paolo Tacconi
1806da0851 Updated Italian strings 2016-04-15 09:09:59 +02:00
redmatrix
521641f3a8 filter out a bit more dreport noise - especially for private posts to multiple recipients. 2016-04-14 21:53:39 -07:00
redmatrix
a29c0371f1 commit 1.4 2016-04-14 20:11:36 -07:00
redmatrix
a8f7af2079 provide general purpose verification class, remove include/session.php (no longer used) 2016-04-14 18:51:06 -07:00
redmatrix
7ae7fac234 Merge branch 'master' into dev 2016-04-14 17:35:47 -07:00
redmatrix
d1fb4e9b03 revup #337 2016-04-14 17:34:08 -07:00
redmatrix
ed0bff798b fix marked bug in code 2016-04-13 22:58:37 -07:00
redmatrix
3f0bb1bb1d Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-13 16:37:10 -07:00
redmatrix
9a0b61e4af refactor the js detection into a checkjs class which is only enabled on demand (currently only the channel and display pages). Will probably require a bit more work to hide/disable the cover photo when js is disabled. Have not actually tested without js to discover any other potential page issues. Have only confirmed that the detection class works and redirects to set a jsdisabled cookie and reload the page with that cookie+variable set if called from the channel page. 2016-04-13 16:31:06 -07:00
Mario Vavti
b81291cd5c some bbcode autocomplete refinement for edit webpage 2016-04-13 11:56:43 +02:00
redmatrix
a8a0ca8291 Merge branch 'master' into dev 2016-04-13 01:02:23 -07:00
redmatrix
1c61be4113 issue #337 2016-04-13 01:01:01 -07:00
redmatrix
91cc365143 reverse the logic of the jsenabled setting so that sessions without js are performance penalised instead of regular sessions. 2016-04-12 22:55:26 -07:00
redmatrix
f4a27afee9 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-12 19:42:02 -07:00
redmatrix
be654f1769 Important work on the sessionhandler to maintain compatibility with php7 and php5x (x > 4)
Merge branch 'master' into dev
2016-04-12 19:40:19 -07:00
redmatrix
73628db7e2 revup issue #337 2016-04-12 18:43:50 -07:00
Mario Vavti
571c72f853 improve bbco autocomplete to not execute listNewLineAutocomplete() many times after many ajax page reloads 2016-04-12 11:55:50 +02:00
redmatrix
b788b38edf remove obsolete jotVideoURL() and jotAudioURL() 2016-04-11 21:40:03 -07:00
redmatrix
09861abab7 when saving bookmarks from a post allow choice of bookmark to be saved (default is all of them); this implements the backend. Additional work will be required on the front end or within plugins to make this happen. 2016-04-11 20:53:08 -07:00
redmatrix
202035fc68 move all DB session storage logic to SessionHandler where it belongs 2016-04-11 19:19:58 -07:00
redmatrix
5ab1d509d2 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-11 13:04:17 -07:00
redmatrix
1b83d88fe6 remove references to ref_session_write - can't use 2016-04-11 13:03:34 -07:00
Mario Vavti
482962648f whitespace 2016-04-11 11:01:53 +02:00
redmatrix
326f3cfc85 Merge branch 'master' into dev 2016-04-11 00:52:34 -07:00
redmatrix
4ba8526745 revup 2016-04-11 00:50:50 -07:00
redmatrix
0269825bc0 localise the opensearch link 2016-04-10 21:56:16 -07:00
redmatrix
5cb3143c04 issue #331 use timeago.js for reshared publish date instead of relative_date() which does not play well with other networks. 2016-04-10 21:30:35 -07:00
redmatrix
d1a2aecfa0 move more session related stuff such as paranoia handling (IP address changes) into the session object and extend remember_me cookies once a day so that they will never expire (theoretically). The DB session driver will extend its expiration on every session write (in the case of persistent sessions). 2016-04-10 19:20:41 -07:00
redmatrix
0fe4957274 when setting the session handler as an object using the auto register shutdown flag, explicitly calling session_write_close() should no longer be required. It shouldn't cause any issues if it is called twice, but the session driver interface has been known to sometimes act in unexpected ways and there are lots of "subtleties" which can often be difficult to debug. The mentioned flag implies PHP 5.4 minimum but I believe we require that anyway. 2016-04-10 17:42:32 -07:00
redmatrix
e9f1bac062 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-10 17:03:30 -07:00
redmatrix
58692e3565 Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-04-10 17:02:26 -07:00
redmatrix
7db733c9a0 revup 2016-04-10 17:02:08 -07:00
redmatrix
abfbe9c937 a few issues: block public not blocking mod_cal, typo in sql for one clone file sync operation, fix_system_urls not catching cached contact photos, extend sessionhandler expiration when remember_me is enabled as the stored session is expiring long before the browser session. 2016-04-10 16:56:08 -07:00
jeroenpraat
f437705007 Update Dutch and Spanish 2016-04-10 20:58:00 +02:00
Mario Vavti
46ed79c87a fix autocomplete for /channel and /display 2016-04-09 12:27:36 +02:00
Mario Vavti
e2b4d33627 some work on comanche autocomplete 2016-04-09 12:16:42 +02:00
Mario Vavti
7690dca67b enable bbcode autocomplete for other places 2016-04-09 09:24:14 +02:00
redmatrix
c0bdcfedeb log if the session handler fails and surface the ssl_cookie config setting 2016-04-08 05:10:36 -07:00
redmatrix
9b66b5eee3 objectify all the session management stuff 2016-04-08 04:44:10 -07:00
redmatrix
2db59f3b76 Merge branch 'master' into dev 2016-04-08 03:32:28 -07:00
redmatrix
44e21f6198 revup 2016-04-08 03:31:32 -07:00
redmatrix
279f32b13d send file sync packets for all known file operations 2016-04-07 18:54:48 -07:00
redmatrix
3a6187af3d implement updates of attach data to sync'd clones. 2016-04-07 16:44:53 -07:00
redmatrix
516f776c94 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-07 16:25:16 -07:00
redmatrix
cc62793d6f Merge branch 'master' into dev 2016-04-07 16:24:59 -07:00
redmatrix
d87daaedd1 revup issue #337 2016-04-07 16:23:57 -07:00
Mario Vavti
cf84ff3344 translate the most common bbcodes to their *real name*. finally we should probably use an array for each bbcode containing the bbcode the real name and possibly a template for use as a peview in the dropdown 2016-04-07 23:03:55 +02:00
Mario Vavti
e419b2c18c some more autocompletion for bbcode tables - leave it open if we wanna use th or td though 2016-04-07 11:34:38 +02:00
Mario Vavti
58324473a9 move li back in the list since it will be used far less than list 2016-04-07 11:16:30 +02:00
redmatrix
62d842de31 Merge branch 'master' into dev 2016-04-06 22:23:07 -07:00
redmatrix
aa678ba0ff reset profile photo and cover photo bits for existing photos if a new one arrives from a clone 2016-04-06 22:14:05 -07:00
redmatrix
e4391e6336 missing profile photo in export data 2016-04-06 21:36:47 -07:00
redmatrix
aa0412d83b use the explicit form of build_sync_packet so that file/photo sync will work even when the actual observer is a guest (with permission to upload). 2016-04-06 20:25:52 -07:00
redmatrix
861f5232d3 more work on file sync to clones, 60-70% test coverage, mostly working but many changes made during testing which themselves have not yet been tested 2016-04-06 19:56:38 -07:00
redmatrix
9831ad515d file sync testing continued 2016-04-06 18:46:29 -07:00
redmatrix
6650916435 file sync testing 2016-04-06 18:38:48 -07:00
redmatrix
64cc0b794a Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-06 18:08:06 -07:00
redmatrix
29363a185d file sync work 2016-04-06 18:07:29 -07:00
Mario Vavti
e41082dccc automate bbcode list creation even further 2016-04-07 00:46:45 +02:00
Mario Vavti
97ccbf1bfb adjust the regex to also work with asteriks and use the simpler syntax for lists 2016-04-06 22:18:59 +02:00
redmatrix
a20ef706fd issue #340 2016-04-06 05:44:40 -07:00
redmatrix
adad8f2ebc getting file sync data - missed parent folder 2016-04-06 05:20:55 -07:00
redmatrix
0533db5d38 revup issue #337 2016-04-06 02:33:58 -07:00
redmatrix
fb9c12df15 rework the "remember me" fix to be a bit less hackish 2016-04-06 02:33:11 -07:00
redmatrix
5a2a8717e3 provide function to collect file/photo sync data per help/filesync 2016-04-05 23:11:24 -07:00
redmatrix
0d50d29538 Merge branch 'master' into dev 2016-04-05 22:15:29 -07:00
redmatrix
54aa998b52 undeclared static property App::$stringsave (push_lang() and pop_lang()) 2016-04-05 22:13:56 -07:00
redmatrix
10f1e2d51b add some doco to getfile module 2016-04-05 21:20:23 -07:00
redmatrix
9fd8634b62 server side of file/photo sync to deliver the file data. We'll sign it using our channel_hash and the current time to make it difficult to forge a request; as the sync process is not going to have magic-auth ability. 2016-04-05 21:10:08 -07:00
redmatrix
fd07940b10 provide stream resource pointer option to z_fetch_url() and z_post_url() per earlier doco commit on syncing files/photos across clones. 2016-04-05 18:24:24 -07:00
redmatrix
6f6051f7e3 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-05 16:44:11 -07:00
redmatrix
f9778fda83 add some doco on some of the issues and approaches to file/photo syncing and cloning 2016-04-05 16:42:33 -07:00
redmatrix
ea3fb53e4b Merge pull request #339 from anaqreon/autocomplete
Improve (un)ordered list autocompletion for list construction
2016-04-06 06:07:32 +10:00
redmatrix
a7d5bf6854 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-05 12:51:22 -07:00
redmatrix
0e7a963173 Merge branch 'master' into dev 2016-04-05 12:51:06 -07:00
redmatrix
4aa2733699 revup issue #337 2016-04-05 12:49:58 -07:00
Andrew Manning
1eb6067c31 Improve (un)ordered list autocompletion for list construction 2016-04-05 14:46:16 -04:00
Mario Vavti
bd29551f9a fix contextual help 2016-04-05 16:59:32 +02:00
Mario Vavti
32ccdd1f57 use min version of justifiedGallery 2016-04-05 15:28:39 +02:00
Mario Vavti
deaf0e99fd expand list of bbcode in autocomplete 2016-04-05 15:27:45 +02:00
Mario Vavti
d99a1d8de0 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-04-05 15:24:42 +02:00
Mario Vavti
0012030826 update upstream lib jusutifiedGallery 2016-04-05 15:24:05 +02:00
redmatrix
ec41170121 Merge pull request #338 from anaqreon/contextual-help
Contextual help
2016-04-05 22:43:15 +10:00
redmatrix
1d5ea5efae explain the two aspects of federation which need to be handled in core to pass comments successfully amongst sites which optionally provide federation. Let's hope this list doesn't grow. 2016-04-04 17:02:27 -07:00
redmatrix
01ad485f65 SECURITY: Do not link unknown and unverified code repositories to the project without some form of confirmation that one accepts the significant risks involved. 2016-04-04 16:17:50 -07:00
redmatrix
447c59fd9b Merge branch 'master' into dev 2016-04-04 13:32:58 -07:00
redmatrix
3de40bdf04 Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-04-04 13:31:31 -07:00
redmatrix
ba6c346b46 revup - issue #337 2016-04-04 13:30:59 -07:00
Mario Vavti
1c9f773900 Merge branch 'master' into dev 2016-04-04 17:13:10 +02:00
Mario Vavti
ec651f219e a simple autocomplete for bbcode or comanche - partly implemented 2016-04-04 17:12:23 +02:00
Mario Vavti
ee8a9384d5 Merge branch 'master' into dev 2016-04-04 10:37:20 +02:00
Mario Vavti
bba34a7a8e do not use dropdown class if there is nothing to dropdown 2016-04-04 10:37:07 +02:00
Mario Vavti
dfa12b2919 Merge branch 'master' into dev 2016-04-04 10:13:30 +02:00
Mario Vavti
9b9f29a0b2 whitespace 2016-04-04 10:10:19 +02:00
Mario Vavti
4a9aad2a33 whitespace 2016-04-04 10:09:46 +02:00
Mario Vavti
69617b5c34 fullscreen mode for photo albums view 2016-04-04 10:09:13 +02:00
redmatrix
222ace3770 For GNU-social discovery, use the URI in the feed (author.uri) rather than try to pick out which of the aliases in webfinger are likely to be the right one. If we get it wrong, our communications with them will be discarded and there is no rhyme or reason to the logic about which representation is likely to be the one true account URI. It appears to vary with the clean_url setting of the site and this info isn't available to us except with a sequence of expensive probes and testing various ways of re-writing URLs to see if we get a response. 2016-04-03 20:55:38 -07:00
redmatrix
2e7d2a63c3 provide a backup copy of prior notes widget content if the contents were just nuked. 2016-04-03 19:34:19 -07:00
Andrew Manning
0523b4b2f1 Merge branch 'master' of https://github.com/redmatrix/hubzilla into contextual-help 2016-04-03 21:36:29 -04:00
redmatrix
a703835b5c Bug: "remember me" doesn't 2016-04-03 17:38:17 -07:00
redmatrix
bf3f3564e0 issue #138 ; make ajaxchat optional and configurable. For reasons we've discussed repeatedly the ajax chat will not be removed from core as XMPP chat does not provide decentralised access control compatible with nomadic identity. 2016-04-03 16:41:40 -07:00
redmatrix
102d41ccb9 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-03 16:17:54 -07:00
redmatrix
cfad5ba8b8 Merge branch 'master' into dev 2016-04-03 16:17:31 -07:00
redmatrix
b4c1baada1 Merge branch 'master' of https://github.com/redmatrix/hubzilla into master_merge 2016-04-03 16:16:14 -07:00
redmatrix
1ca3eeedff issue #337 2016-04-03 16:15:41 -07:00
Mario Vavti
298b53e93a Merge branch 'master' into dev 2016-04-03 18:00:25 +02:00
Mario Vavti
f13096a6f3 various fixes 2016-04-03 18:00:03 +02:00
Mario Vavti
470f14b919 Merge branch 'master' into dev 2016-04-03 15:27:26 +02:00
Mario Vavti
53311a30ad reduce chat-item-title fontsize to match wall-item-ago 2016-04-03 15:27:10 +02:00
Mario Vavti
5634a4bb61 Merge branch 'master' into dev 2016-04-03 14:56:52 +02:00
Mario Vavti
738e14348d update upstream libs fullcalendar and moment to a recent version 2016-04-03 14:56:19 +02:00
Mario Vavti
787e2ef961 Merge branch 'master' into dev 2016-04-03 12:20:10 +02:00
Mario Vavti
db4e9aeaad fullscreen mode for events 2016-04-03 12:19:49 +02:00
Mario Vavti
7850b04853 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev 2016-04-03 11:35:47 +02:00
Mario Vavti
b6f18a9a0b Merge branch 'master' into dev 2016-04-03 11:35:06 +02:00
Mario Vavti
b8d8be7013 show chat expiration time in overview and minor fixes 2016-04-03 11:34:07 +02:00
redmatrix
84feff9500 Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge 2016-04-02 21:09:05 -07:00
redmatrix
81ba293561 Merge branch 'master' into dev 2016-04-02 21:07:34 -07:00
redmatrix
8b3c099a12 use constant 2016-04-02 21:06:41 -07:00
Mario Vavti
2772a72095 ge branch 'master' into dev 2016-04-03 00:19:30 +02:00
Mario Vavti
e361ee9253 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-04-03 00:04:30 +02:00
Mario Vavti
3edd4ce78f ease transition between fullscreen and inline view for small screens 2016-04-03 00:04:05 +02:00
redmatrix
381cc3e6f8 Merge branch 'master' into dev 2016-04-02 13:54:49 -07:00
redmatrix
d09694587d typo in router 2016-04-02 13:52:16 -07:00
redmatrix
63451db3f6 small changes in README.md 2016-04-02 01:47:46 -07:00
redmatrix
7660afdb0f revup 2016-04-02 00:28:51 -07:00
jeroenpraat
72d995d35f Update nl and es-es strings 2016-04-01 23:24:13 +02:00
redmatrix
2a32df75f1 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-04-01 03:27:46 -07:00
redmatrix
e16da7a166 unreferenced app member 2016-04-01 03:27:21 -07:00
Mario Vavti
5b55726a93 on update only jump to bottom if we actually got a new message 2016-04-01 11:13:04 +02:00
Mario Vavti
bbe93d0e1d scroll chat to bottom on fullscreen toggle 2016-04-01 10:29:58 +02:00
Mario Vavti
5dd422e2d8 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-04-01 10:20:26 +02:00
Mario Vavti
a564f495a7 improve scroll to bottom in chat 2016-04-01 10:20:10 +02:00
redmatrix
995555f357 ditto for typohelper 2016-04-01 01:04:37 -07:00
redmatrix
40f3857691 change call to App::init() to bring back include path (only in typocheck) 2016-04-01 01:02:03 -07:00
redmatrix
5d884c2f3d suddenly we have includepath issues - provide the explicit paths 2016-04-01 00:59:30 -07:00
redmatrix
8f006a98c4 primary hub change 2016-04-01 00:54:23 -07:00
Mario Vavti
ebac0bdcca Chat Rooms -> Chatrooms 2016-04-01 09:46:41 +02:00
Mario Vavti
3575ef8a39 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-04-01 08:57:05 +02:00
Mario Vavti
60bb8f25f7 move fullscreen js code to redbasic.js where it belongs to 2016-04-01 08:56:51 +02:00
redmatrix
2d3dd673e4 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-31 23:41:41 -07:00
redmatrix
9d47de65d9 undeclared static vars 2016-03-31 23:41:20 -07:00
Mario Vavti
c6d9100649 missing template 2016-04-01 08:36:02 +02:00
redmatrix
44283dbbbb change the App constructor 2016-03-31 20:24:30 -07:00
redmatrix
0cda431456 create miniApp to convert existing settings files to the static App class 2016-03-31 20:15:47 -07:00
redmatrix
bbfe4de310 increment std_version 2016-03-31 18:57:44 -07:00
redmatrix
36b388ab8c issue #336 2016-03-31 18:53:05 -07:00
redmatrix
c0b3d7e1b4 Merge branch 'static' 2016-03-31 17:32:51 -07:00
redmatrix
9abd95fad3 static App 2016-03-31 16:06:03 -07:00
Mario Vavti
50d9b29347 slightly change the way fullscreen works and bring it to mod mail 2016-04-01 00:16:39 +02:00
Mario Vavti
90a5ba01a3 make fullscreen mode available for other modules and some cleanup 2016-03-31 23:13:40 +02:00
Mario Vavti
6c2673ae2a various fixes regarding mod chat 2016-03-31 22:42:28 +02:00
redmatrix
256c228efd initial conversion to static app class 2016-03-31 13:00:04 -07:00
Mario Vavti
3fdd110e07 mod chat rework continued 2016-03-31 13:21:48 +02:00
redmatrix
1cd3b41825 deprecate $a->get_baseurl() 2016-03-30 22:13:24 -07:00
redmatrix
4148211086 change primary directory 2016-03-30 18:37:37 -07:00
redmatrix
4ba9a5ef75 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-30 16:39:08 -07:00
redmatrix
6a6dbec033 issue #319 - NOTE: this does not fix the issue, it only reports it and continues. We need to examine any logger statements that contain 'stack:' as a result of reporting this issue and find and fix the original problem - which is that set_pconfig is being called without a valid $uid. I'm worried that since we will now continue on without throwing a PHP error that nobody will ever notice or find the problem that is causing this. 2016-03-30 16:33:23 -07:00
Mario Vavti
df891f4ad2 more work on mod chat 2016-03-31 00:37:40 +02:00
Mario Vavti
08461c7049 more on mod chat 2016-03-30 14:44:03 +02:00
Mario Vavti
5462453bf2 some work on mod chat 2016-03-30 14:31:55 +02:00
redmatrix
e4f3605054 add page title to the html title 2016-03-29 14:14:17 -07:00
redmatrix
f65ede9c38 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-28 16:08:31 -07:00
redmatrix
a6ad37c691 revup 2016-03-28 16:08:11 -07:00
Mario Vavti
ba0812c447 highlight table row on hover 2016-03-27 22:37:07 +02:00
jeroenpraat
dbde9a0940 Update es_es+n. Switch the feeds as requested by Mike. 2016-03-27 14:03:02 +02:00
redmatrix
d3f38c9f43 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-26 14:34:19 -07:00
redmatrix
971e7321c6 issue #319 part 2 2016-03-26 14:33:36 -07:00
jeroenpraat
eeb1c463e3 Small, but I think useful hack. Added a top posts only atom feed, so people can choose directly from their browser which feed they need. 2016-03-26 22:32:46 +01:00
Andrew Manning
99d9456b3a More help content for channel pages. Channel, photos, files, about. 2016-03-26 14:55:16 -04:00
Mario Vavti
97eef2b88c removed link to connected apps by accident 2016-03-26 19:34:38 +01:00
Andrew Manning
c25ef1d9a8 Search docs/context/ hierarchically for help.html files to reduce redundancy 2016-03-26 14:31:41 -04:00
Andrew Manning
661b0084f3 Added help for post permissions 2016-03-26 14:17:53 -04:00
Mario Vavti
f714e97d63 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-26 18:46:07 +01:00
Mario Vavti
a507063174 move link to /locs to settings menu if we have more than one location and some template work on locs 2016-03-26 18:43:38 +01:00
git-marijus
3caf51b075 Merge pull request #333 from phellmes/de20160324
Update DE translation strings
2016-03-25 10:26:12 +01:00
redmatrix
92ec46b62e revup 2016-03-24 19:18:25 -07:00
phellmes
9b06d952a2 Update DE translation strings 2016-03-24 09:08:12 +01:00
redmatrix
531710142c add hook to allow plugins to perform a follow activity from an activityfeed 2016-03-23 20:04:09 -07:00
Andrew Manning
59827b6dfd Merge branch 'master' of https://github.com/redmatrix/hubzilla into contextual-help 2016-03-23 21:17:23 -04:00
Andrew Manning
61bef7d4b0 Network page help with auto-scroll and element highlighting 2016-03-23 21:16:21 -04:00
redmatrix
f200dd4395 atom specifies a uri or iri for the id. message_id isn't suitable here. 2016-03-23 16:36:27 -07:00
redmatrix
a8ac0ed549 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-22 19:59:47 -07:00
redmatrix
6f2ba0c619 rewrite the webfinger discovery logic 2016-03-22 19:58:59 -07:00
Wave
0a14ac1f60 Merge pull request #332 from wave72/master
Updated Italian strings
2016-03-22 11:53:57 +01:00
Paolo Tacconi
02140b2f76 Updated Italian strings 2016-03-22 11:49:03 +01:00
Mario Vavti
c6b89b99b9 Add a link to /locs to channel manager 2016-03-22 10:29:17 +01:00
redmatrix
51a840f46a update network_to_name (reserve DFRN for future use) 2016-03-21 22:02:18 -07:00
redmatrix
b081c3e94b Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-21 21:32:35 -07:00
redmatrix
ec99e3ed62 attempting to work with braindead lighttpd gnusocial servers 2016-03-21 21:31:28 -07:00
Mario Vavti
97e1a6dfde whip mod manage into shape 2016-03-22 02:06:19 +01:00
Andrew Manning
56c86b6567 Override navbar help button to open contextual help panel. Contextual help for mail written. 2016-03-21 06:33:02 -04:00
redmatrix
28599fe652 more federation work 2016-03-20 21:41:19 -07:00
redmatrix
d3e7ef70e8 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-20 19:56:36 -07:00
redmatrix
fea532af4d rework salmon - important, update addons also if you have enabled gnusoc addon 2016-03-20 19:55:53 -07:00
Mario Vavti
f5b22dfd5b erge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-21 00:41:09 +01:00
redmatrix
48e62bb50a Merge pull request #329 from git-marijus/master
fix #328 by using a seperate query instead of group_concat
2016-03-21 10:22:30 +11:00
Mario Vavti
513078e1f7 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-20 23:52:55 +01:00
redmatrix
23151100de Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-20 15:32:09 -07:00
redmatrix
eb68b66c58 issue #330 - permit archived connections in ACLs. If they are to be blocked for delivery (or some other purpose) this should probably happen in the delivery mechanism (or other related sub-system) rather than the permissions mechanism, although currently we still attempt direct delivery to archived connections. Technically "archived" means merely that we won't 'poll' the connection according to the current definition. 2016-03-20 15:27:26 -07:00
Mario Vavti
1ddb43b0d3 an attempt to visualize the supremacy of dont show over show in the acl selector 2016-03-20 23:07:39 +01:00
Mario Vavti
9fcd470aca fix #328 by using a seperate query instead of group_concat 2016-03-20 20:26:55 +01:00
jeroenpraat
23419e4c26 Update NL + es_ES strings. 2016-03-20 14:39:22 +01:00
Mario Vavti
34b42566b6 add fixme 2016-03-20 02:25:59 +01:00
Mario Vavti
f7ff48f806 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-20 01:46:13 +01:00
Mario Vavti
30cf56bdb5 make >>indicate group members<< in acl selector work again on group > show or group > dont show is selected 2016-03-20 01:45:56 +01:00
redmatrix
77094f8d2b make the admin side menu extensible and provide a hook for a channel "move" operation that federation plugins might use to re-establish connections after a channel move. 2016-03-19 16:17:19 -07:00
Mario Vavti
51cd4e8519 missing return false for map link 2016-03-19 02:20:59 +01:00
Mario Vavti
bd249b276d add use as cover photo link to photos view 2016-03-18 17:49:31 +01:00
redmatrix
b6ae2bff01 change rev 2016-03-17 18:42:32 -07:00
redmatrix
21c1f89eba SECURITY: DAV authentication issue 2016-03-17 18:40:03 -07:00
redmatrix
df61970b39 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-17 12:16:25 -07:00
redmatrix
f82afca84d no xchan here if using zot protocol 2016-03-17 12:15:28 -07:00
jeroenpraat
eca119d695 See issue https://github.com/redmatrix/hubzilla-addons/issues/17 (UNO: enable the Diaspora protocol for all channels (if addon is enabled) - I had to do this during channel creation and not in the addon itself, or else the member can't change this after the channel is created. Tested it on UNO and normal Hubzilla. If this is not the right place for this, please move it. If not wanted at all, please discuss. 2016-03-17 15:48:44 +01:00
Mario Vavti
40162cd6b7 some work on profile listing 2016-03-17 12:56:55 +01:00
Mario Vavti
a41a05e6c0 bring more structure to profiles edit 2016-03-17 11:50:53 +01:00
redmatrix
a83cdbeb39 typo 2016-03-16 22:02:19 -07:00
redmatrix
6d4fe5c56f Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-16 21:06:15 -07:00
redmatrix
3a8f6e6576 more federation backend 2016-03-16 21:05:52 -07:00
redmatrix
38eb79705e lots of work on federated channel discovery 2016-03-16 18:00:13 -07:00
git-marijus
f7ddd44c2e Merge pull request #327 from anaqreon/ownmapp-typo
Misspelling of ownMapp in homeinstall script
2016-03-16 23:10:24 +01:00
Mario Vavti
2165733ddc move buttons to dropdown menu and some cleanup 2016-03-16 23:07:29 +01:00
Mario Vavti
d22b21c56f still more janitor work on profiles 2016-03-16 13:45:24 +01:00
redmatrix
4188419b30 more federation backend work 2016-03-15 17:54:06 -07:00
Mario Vavti
d98d7003ed even more janitor work on profiles 2016-03-15 21:38:03 +01:00
Andrew Manning
1692380ac7 Misspelling of ownMapp 2016-03-15 10:54:45 -04:00
redmatrix
01a28ddf8d Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-15 01:32:41 -07:00
redmatrix
e8d19659c0 some heavy lifting porting the old salmon code 2016-03-15 00:50:03 -07:00
redmatrix
b673b6835d federation work 2016-03-14 22:14:17 -07:00
redmatrix
ef7494359f some re-working of webfinger and hcard parsing which will be necessary going forward. 2016-03-14 18:12:35 -07:00
jeroenpraat
b8e8517725 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-14 15:46:57 +01:00
jeroenpraat
def0454952 update nl + es-es strings 2016-03-14 15:43:51 +01:00
redmatrix
2f5862713e Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-13 18:16:11 -07:00
redmatrix
6729c27b77 git update everything 2016-03-13 18:15:38 -07:00
redmatrix
fbfa391965 Merge pull request #323 from phellmes/de20160313
Update DE translation strings
2016-03-14 10:45:54 +11:00
Mario Vavti
38beabb508 fix spacing 2016-03-13 21:27:29 +01:00
Mario Vavti
a8d5c83251 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-13 21:19:33 +01:00
Mario Vavti
370a007ee2 more janitor work on profiles 2016-03-13 21:19:15 +01:00
redmatrix
7747a23a78 Merge pull request #324 from einervonvielen/install-script_add-hubsites_stop-hubzilla
Install script: stop of apache, mysql
2016-03-14 06:19:18 +11:00
EinerVonVielen
c573670821 Install script: Added plugin hubsites and stop of apache, mysql 2016-03-13 16:32:34 +01:00
phellmes
a752d44313 Update DE translation strings 2016-03-13 13:29:14 +01:00
redmatrix
9406ff714b Merge pull request #322 from einervonvielen/homeinstall_with_plugins
Added installation of extended plugins and themes to homeinstall script
2016-03-13 15:21:00 +11:00
redmatrix
cc29e27acc issue #320 - regression, after removing channel attached to an authenticated session the session was not completely cleared. 2016-03-12 19:53:07 -08:00
EinerVonVielen
b2563528ee Added installation of extended plugins and themes to homeinstall script 2016-03-13 02:37:38 +01:00
redmatrix
70ad69d38c Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-12 16:47:11 -08:00
redmatrix
cb0c43bc68 provide service federation overview - how to go about it and the appropriate places to attach your plugin. 2016-03-12 16:45:53 -08:00
Mario Vavti
7efffbf102 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-12 22:14:08 +01:00
Mario Vavti
2d8deb6082 some janitor work on profiles 2016-03-12 22:13:46 +01:00
Jeroen van Riet Paap
5de79cdb10 Merge pull request #321 from einervonvielen/fix_german_help_link_to_github
Fix: german help > link to of project in github
2016-03-12 22:04:56 +01:00
EinerVonVielen
6837c2ef1e Fix: German help > link to of project in github. The link Pointed to
redmatrix.
Now the link points to hubzilla.
2016-03-12 21:46:13 +01:00
Mario Vavti
4e9440396c remove superfluous return 2016-03-11 10:54:04 +01:00
redmatrix
32c23ef562 some minor cleanups 2016-03-10 15:43:59 -08:00
jeroenpraat
107f80892a UNO: Hide bookmark tools in items (#^ and in menu) 2016-03-10 19:40:28 +01:00
redmatrix
fbcb711945 we've come a long way since this faq entry on the limits of cloning was written 2016-03-09 19:03:09 -08:00
redmatrix
e95a494041 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-09 16:23:46 -08:00
redmatrix
7732532964 handle UNO move channel operation 2016-03-09 15:56:51 -08:00
jeroenpraat
bb09b8a385 Update doc 2016-03-09 23:25:37 +01:00
redmatrix
b9b46a3f88 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-09 14:18:11 -08:00
redmatrix
7bb461380e issue #319 - make sure we have a local_channel() and an App::channel before trying to change the default schema for a channel 2016-03-09 14:15:50 -08:00
redmatrix
f5f79b39b8 Merge pull request #318 from git-marijus/master
should have probably done that on tag release
2016-03-10 09:03:59 +11:00
Mario Vavti
14e55e8bd6 should have probably done that on tag release 2016-03-09 13:06:24 +01:00
redmatrix
bc9d5f5a48 Merge pull request #317 from git-marijus/master
Issue #316 make /display updates work. Basically copy and paste what …
2016-03-09 20:10:48 +11:00
Mario Vavti
c2cdd41e81 Issue #316 make /display updates work. Basically copy and paste what we do on load and add $simple_update to the query. 2016-03-09 10:04:33 +01:00
redmatrix
256cd6baac work on implementing account/channel move (as opposed to clone) 2016-03-09 00:46:17 -08:00
redmatrix
843cc1481a isue #315 2016-03-08 16:46:47 -08:00
redmatrix
cf4dc2caa8 move "generator" to HttpMeta 2016-03-08 16:21:35 -08:00
redmatrix
1258f9bb21 turn 'OpenGraph' into a more general purpose HTTP meta facility for setting any meta header 2016-03-08 16:06:58 -08:00
redmatrix
5f41d06bb9 revup 2016-03-08 15:50:34 -08:00
Wave
8f4fe106ef Merge pull request #314 from wave72/master
Updated Italian strings
2016-03-08 15:54:54 +01:00
Paolo Tacconi
d74274c7e4 Updated Italian strings 2016-03-08 15:51:21 +01:00
Mario Vavti
d59268a5d8 removed id by mistake - add it again 2016-03-08 11:47:17 +01:00
Mario Vavti
f364343b55 add generic-content-wrapper and setction-content-wrapper to profile_edit.tpl 2016-03-08 11:43:21 +01:00
redmatrix
9debfa348a add syslog loglevels to dba functions 2016-03-07 20:43:52 -08:00
redmatrix
32e903e956 a bit of page cleanup for edit profiles 2016-03-07 18:49:17 -08:00
redmatrix
bd8fe768d3 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-07 16:55:12 -08:00
redmatrix
848c038970 issue #313 2016-03-07 16:54:58 -08:00
jeroenpraat
24fa201218 Small, but important fix for Dutch 2016-03-08 01:47:01 +01:00
redmatrix
1a77fb4c1d Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-07 15:12:09 -08:00
redmatrix
76467b5a35 allow modules/addons to override the og:title field 2016-03-07 15:11:11 -08:00
redmatrix
d5db25808a Facebook scraper "OpenGraph" support; modules will need to set the required fields (type, image, url) as well as any desired optional or type specific fields. We will set the title during pagebuild. 2016-03-07 15:03:53 -08:00
Mario Vavti
6824fb9f93 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-07 21:48:12 +01:00
Mario Vavti
b2216f8203 prevent page jumping if the narrow navbar setting is used 2016-03-07 21:47:52 +01:00
jeroenpraat
0799a0a3be Spanish and Dutch strings + fix es>es-es link 2016-03-07 20:29:14 +01:00
redmatrix
a2e0574fce Merge pull request #312 from jeroenpraat/master
Redbasic: Fix the issue with derived themes and schemas
2016-03-08 06:03:55 +11:00
Jeroen van Riet Paap
68d7ab6b55 Merge pull request #308 from HaakonME/master
Updated Norwegian strings for Hubzilla.

@HaakonME Can you please check if this commit is correct: https://github.com/redmatrix/hubzilla/pull/308/files#diff-8844953d2396d7486ea8e8b194c1ce96
2016-03-07 19:53:58 +01:00
Jeroen van Riet Paap
4a2c805270 Merge pull request #310 from einervonvielen/updated_homeinstall_instructions
Updated readme.md for homeinstall script
2016-03-07 19:49:58 +01:00
Jeroen van Riet Paap
7d5b266227 Merge pull request #309 from tluther/master
Doco / EMail templates
2016-03-07 19:47:47 +01:00
Jeroen van Riet Paap
1f56ff5407 Update DerivedTheme1.md 2016-03-07 17:07:34 +01:00
Jeroen van Riet Paap
95f5f3d44d Show only schema selector when Redbasic (so not a derived theme) 2016-03-07 17:06:10 +01:00
Jeroen van Riet Paap
7a5213cc8e Set the schema to the default schema in derived themes.
See the documentation for creating derived themes how to override this.
2016-03-07 17:03:02 +01:00
Jeroen van Riet Paap
f1f19372ad Update config.php 2016-03-07 17:01:12 +01:00
Haakon Meland Eriksen
276f44328e Merge remote-tracking branch 'upstream/master' 2016-03-07 06:00:26 +01:00
redmatrix
da3f1326e0 revup 2016-03-06 15:32:46 -08:00
Tobias Luther
a013ddbb91 Doc: Minor correction cloud URL in cloud.bb 2016-03-06 21:32:36 +01:00
Tobias Luther
1c6faa3a00 Added Link to TOS to EMail templates targeting members 2016-03-06 18:45:43 +01:00
einervonvielen
b7f15ccac1 Update of readme according to the last changes
The homeinstall script was changed recently. To reflect these changes the readme.md was updated to.
2016-03-06 18:40:49 +01:00
www-data
1fb7b9baae Doco: corrected git URL in git for non-developers 2016-03-06 18:34:50 +01:00
Haakon Meland Eriksen
a1e4940bea Merge remote-tracking branch 'upstream/master' 2016-03-06 18:33:28 +01:00
root
287ffe93f6 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-06 17:24:15 +01:00
root
2407379623 Das ist notwendig, um weiter zu arbeien. Merge branch 'master' of https://github.com/einervonvielen/hubzilla 2016-03-06 17:19:33 +01:00
jeroenpraat
7162403292 Also make it clear with (mouse) hover text that you must click on the cover photo to show the channel/more 2016-03-06 17:02:58 +01:00
jeroenpraat
004468f231 Mouse cursor set to pointer for coverphoto div (instead of arrow). Or else it's not clear that you can click on it to show something (the channel in this case). 2016-03-06 16:21:26 +01:00
Haakon Meland Eriksen
2d7e307e74 Updated Norwegian strings for Hubzilla 2016-03-05 14:11:56 +01:00
Haakon Meland Eriksen
d7466ade46 Merge remote-tracking branch 'upstream/master' 2016-03-05 10:01:42 +01:00
Haakon Meland Eriksen
01c0e5c46c Merge remote-tracking branch 'upstream/master' 2016-03-04 23:42:30 +01:00
redmatrix
86f840843f Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-04 14:38:47 -08:00
redmatrix
9a0f0181a5 issues #306 and #307 2016-03-04 14:38:14 -08:00
Mario Vavti
25ebac8d0b show cover-photo upload link only for the default profile 2016-03-04 16:07:41 +01:00
Mario Vavti
edf6da7189 add cover photo upload link to edit profile 2016-03-04 15:44:33 +01:00
Haakon Meland Eriksen
059da4d017 Merge remote-tracking branch 'upstream/master' 2016-03-04 06:05:47 +01:00
redmatrix
a59d1b22f6 Update the CHANGELOG for V1.3 2016-03-03 18:55:10 -08:00
redmatrix
dd4a66353a Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-03 14:49:34 -08:00
redmatrix
2cf54c465d remove the markdown feature. Do not re-enable unless you are willing to support it. 2016-03-03 14:47:39 -08:00
Mario Vavti
d3491c9165 fix jot form 2016-03-03 13:46:08 +01:00
Mario Vavti
8ca877bdd3 slide up cover on click 2016-03-03 12:31:49 +01:00
Mario Vavti
b704f977da Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-03 12:08:21 +01:00
Mario Vavti
59e04aed1b move cover-photo to template, add the ability to define a title and subtitle (defaults to channel name and addres), move js from redbasic.js to template. 2016-03-03 12:07:58 +01:00
redmatrix
436e91a1e1 rename the menu entry and page to 'Profile Fields' to maintain consistency 2016-03-02 16:39:34 -08:00
redmatrix
6f4c45a489 UI cleanup for admin profile field management page 2016-03-02 15:36:14 -08:00
redmatrix
157bbb14b5 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-02 11:35:48 -08:00
redmatrix
5c22f59c4f issue #305 2016-03-02 11:32:32 -08:00
Jeroen van Riet Paap
aa62bad07b little nl string fix 2016-03-02 15:33:18 +01:00
Mario Vavti
d3f2d2a2db small fix to simple cover-photo 2016-03-02 14:30:33 +01:00
Mario Vavti
c5d08fd5fd add a fade in effect to main while scrolling up cover photo 2016-03-02 13:33:18 +01:00
Mario Vavti
22729da2a2 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-02 12:31:46 +01:00
Mario Vavti
c97cc1487c a simple cover-photo implementation for redbasic default template 2016-03-02 12:31:25 +01:00
redmatrix
428b4dbad6 sort out the with and howlong dependencies 2016-03-01 22:47:07 -08:00
Haakon Meland Eriksen
264abef817 Merge remote-tracking branch 'upstream/master' 2016-03-02 06:06:39 +01:00
redmatrix
548bf884a4 profile field admin page (functional only: still needs a lot of HTML/CSS cleanup) 2016-03-01 21:06:27 -08:00
redmatrix
a0baa480e3 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-03-01 15:01:48 -08:00
redmatrix
765dd5569b Allow configuration of the display order of profile fields. This is an important piece of a more general profile configuration framework which will eventually be accessible via the admin page. 2016-03-01 14:55:04 -08:00
redmatrix
c19a1a6b82 revup 2016-03-01 14:13:38 -08:00
jeroenpraat
8b61e546fe Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-01 22:09:06 +01:00
jeroenpraat
7206e8af3a Small fix for deleted forum channels showing in the forum widget (had this after migration from RM on 1 or 2 channels) 2016-03-01 22:08:50 +01:00
Mario Vavti
7808689198 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-03-01 20:40:33 +01:00
Mario Vavti
966d1586c0 fix js error and add id to field input block 2016-03-01 20:40:11 +01:00
redmatrix
edffd9f183 Merge pull request #304 from phormanns/master
fix typo in postgres schema
2016-03-02 06:22:46 +11:00
Peter Hormanns
7edc505c2f fix typo in postgres schema 2016-03-01 17:54:52 +01:00
Mario Vavti
4df78b06cf fix padding 2016-03-01 15:11:15 +01:00
Mario Vavti
492609d20b do not show empty buttons if not logged in 2016-03-01 14:41:14 +01:00
Mario Vavti
0f76af261c another resize issue 2016-03-01 14:11:42 +01:00
Mario Vavti
9d00db06b2 fix resize issue 2016-03-01 14:03:34 +01:00
Mario Vavti
141f3e21b2 move preview content outside of editor space 2016-03-01 13:40:19 +01:00
Mario Vavti
fe6cbb414c adjust padding 2016-03-01 13:32:18 +01:00
Mario Vavti
e13d65eea3 set line-height to initial 2016-03-01 13:29:59 +01:00
Mario Vavti
4d6050f8e5 another css fix 2016-03-01 13:22:19 +01:00
Mario Vavti
0ebce75c7d css fixes to make jot look better with background colors or images 2016-03-01 13:09:04 +01:00
redmatrix
91bb4bdf50 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-29 19:34:23 -08:00
redmatrix
be2b7c0b5f abconfig 2016-02-29 19:31:52 -08:00
Mario Vavti
2d45f9f385 provide footer bbcode 2016-02-29 23:58:32 +01:00
redmatrix
44b2503572 revup 2016-02-29 13:42:30 -08:00
Mario Vavti
3f90da5643 remove unused variable 2016-02-29 22:07:14 +01:00
Mario Vavti
d27a627c4f simplify profile edit button(s) and make it useful for multiple profiles 2016-02-29 22:01:13 +01:00
jeroenpraat
55ab5360d9 update es-es. tested it and it works now. Don't know what happened earlier. 2016-02-29 19:36:53 +01:00
Mario Vavti
bfeeb76143 fix deletion of files from filesystem 2016-02-29 15:37:34 +01:00
Mario Vavti
f2d3be2e67 do not process update activity if there is no item to update and simplify code a little 2016-02-29 14:22:35 +01:00
jeroenpraat
60b818eb24 revert es-es update. something went wrong. later today I will examine what. 2016-02-29 09:07:29 +01:00
redmatrix
ebe70a41b9 build_sync_packet - no need to sleep after the last sync delivery. 2016-02-28 18:26:08 -08:00
redmatrix
da79662081 stop the PHP warnings from Thomas's buggered sitekey 2016-02-28 16:33:52 -08:00
redmatrix
72f3f7c172 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-28 15:07:00 -08:00
redmatrix
713a796d9f revup 2016-02-28 15:06:42 -08:00
jeroenpraat
69c6d8b617 update es-es strings 2016-02-28 17:33:22 +01:00
Haakon Meland Eriksen
e084a85e79 Merge remote-tracking branch 'upstream/master' 2016-02-28 09:10:39 +01:00
redmatrix
a1f046992d I haven't investigated 'why', but the addition of the router class in 1db3409f36 resulted in the setup global variable $install_wizard_pass to not get initiated at the global level when the setup module file was included. This corrects the situation and makes install work but without explaining why the variable wasn't instantiated in the first place. This may be important - if any other modules use global variables internally. I don't believe that any do, but the behaviour needs to be resolved or documented. 2016-02-27 17:27:46 -08:00
redmatrix
cd5630476f Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-27 16:29:13 -08:00
redmatrix
f7f20c5917 z_fetch_url and z_post_url returning false 2016-02-27 16:27:37 -08:00
redmatrix
44797fe988 Merge pull request #302 from phellmes/de20160227
Update DE translation strings
2016-02-28 09:57:04 +11:00
Haakon Meland Eriksen
c5333b5187 Merge remote-tracking branch 'upstream/master' 2016-02-27 21:40:00 +01:00
Mario Vavti
2d045a12bf Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-02-27 16:52:11 +01:00
Mario Vavti
a2fe22412f missing include 2016-02-27 16:51:54 +01:00
jeroenpraat
df69465357 update NL strings 2016-02-27 15:56:45 +01:00
phellmes
e4361cb202 Update DE translation strings 2016-02-27 14:28:06 +01:00
Mario Vavti
58cf9d832c make attach_delete() return and comment out album rename functionality since this is not supported by the backend at the moment. 2016-02-27 12:31:07 +01:00
Haakon Meland Eriksen
cf5383fdbe Merge remote-tracking branch 'upstream/master' 2016-02-27 11:24:02 +01:00
redmatrix
6126070a1d Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-26 12:49:02 -08:00
redmatrix
459166116d turn timezone aware birthdays into a feature for those who want an uncluttered calendar - at the expense of possibly sending somebody's birthday greeting on the wrong day if they are in a different timezone. 2016-02-26 12:45:44 -08:00
Mario Vavti
776bc51172 fix link to photo album and make sure that small photos are not overwritten by body text. 2016-02-26 15:21:14 +01:00
Mario Vavti
df57c90d2d several photo item template fixes 2016-02-26 14:25:18 +01:00
Mario Vavti
5a563b8e76 some improvement for file activity 2016-02-26 11:17:21 +01:00
Mario Vavti
0653a2e0a9 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-02-26 09:21:01 +01:00
Mario Vavti
d19dfc87a6 get rid of duplicate function 2016-02-26 09:20:44 +01:00
redmatrix
dc8c7a2d2e small improvements to profile like activity 2016-02-25 16:21:38 -08:00
redmatrix
ba2ede0a8f this reverts ea54987ca4 2016-02-25 15:41:52 -08:00
redmatrix
6892ba4cd8 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-25 15:14:57 -08:00
Mario Vavti
5ad9b48f1d revert f62ec4132e - allow one self to be added to a privacy group. 2016-02-25 23:59:57 +01:00
redmatrix
7972de13ca backtrace openssl_verify errors so that we can find bad keys - as there is very little relevant context available at this level. 2016-02-25 14:34:30 -08:00
Mario Vavti
ea54987ca4 in update_birthdays() we should probably set adjust to 0 instead of 1 since a birthday is more a kind of a global holiday 2016-02-25 23:03:38 +01:00
Mario Vavti
b2474334a7 provide an edit button for the profile page 2016-02-25 22:50:16 +01:00
redmatrix
2a0d4a2011 Merge pull request #299 from git-marijus/master
we have got a button for events in the nav. no need for it in the tab…
2016-02-26 06:27:42 +11:00
Mario Vavti
be27fb5644 we have got a button for events in the nav. no need for it in the tabs if we are local. 2016-02-25 13:40:15 +01:00
redmatrix
ebfa1a12b9 when creating an event from a post in our stream, if the original post was private, set the event permissions to "just me". If it was a public event, set the event permissions to the channel default permissions. 2016-02-25 00:36:35 -08:00
Haakon Meland Eriksen
21f2df399d Merge remote-tracking branch 'upstream/master' 2016-02-25 06:05:12 +01:00
redmatrix
43521bb10b Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-24 18:56:04 -08:00
redmatrix
c95d7c69eb issue #216 - calendar sharing 2016-02-24 18:54:52 -08:00
jeroenpraat
f12b0fe316 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-02-25 02:05:16 +01:00
jeroenpraat
8944d7a7a2 another dutch update 2016-02-25 02:03:58 +01:00
redmatrix
6300f47cdc schema change to support channel move (a completely different operation than channel clone) 2016-02-24 17:00:16 -08:00
redmatrix
2b95580cc0 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-24 16:41:46 -08:00
jeroenpraat
93b84f1262 interim dutch string update 2016-02-25 01:39:50 +01:00
jeroenpraat
1ffae1327f Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-02-25 01:05:31 +01:00
jeroenpraat
01a8292d65 fix TOS 2016-02-25 01:04:37 +01:00
Mario Vavti
9d3ce55978 fix boxy scheme 2016-02-25 00:24:58 +01:00
redmatrix
7e6febe2a6 add 'requires' field to plugin info to list other dependent plugins/addons and disable if dependencies are not installed/enabled 2016-02-24 15:19:28 -08:00
Mario Vavti
e73df9ed1d give nav dropdowns a fixed width to preventtext-overflow: ellipsis cut of to much of the text in some situations 2016-02-24 23:16:42 +01:00
redmatrix
b101a8f6fb missing function 2016-02-24 11:20:46 -08:00
Haakon Meland Eriksen
ddeab48f9b Merge remote-tracking branch 'upstream/master' 2016-02-24 17:44:27 +01:00
redmatrix
d074c53889 function to process atom stream without actually storing anything 2016-02-23 16:34:53 -08:00
git-marijus
039eb58524 Merge pull request #297 from bashrc/bashrc/comma
Remove stray comma
2016-02-23 22:53:14 +01:00
Bob Mottram
29c9e7c0a2 Remove stray comma 2016-02-23 19:50:45 +00:00
Wave
f15a06c0c2 Merge pull request #296 from wave72/master
Updated Italian strings
2016-02-23 11:55:23 +01:00
Paolo Tacconi
ab89eb050a Updated Italian strings 2016-02-23 11:52:45 +01:00
Mario Vavti
eca1f84328 change wording in case where registration is by apprval only 2016-02-23 11:23:43 +01:00
redmatrix
3bde7b8f18 add salmon key param 2016-02-22 16:20:19 -08:00
jeroenpraat
9db1148650 pubsites: network column is not needed anymore (mentioned in intro text). Because of more vertical space Access and Register columnis separate again. 2016-02-22 19:28:32 +01:00
jeroenpraat
502fed198d only hubs from local configured project on pubsites (hubzilla by default). as agreed with Mike. 2016-02-22 19:10:01 +01:00
Mario Vavti
411c510778 change wording 2016-02-22 13:42:05 +01:00
Mario Vavti
dd6e3d873d some work on mod/register 2016-02-22 13:04:48 +01:00
redmatrix
f9b092c619 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-21 18:15:40 -08:00
redmatrix
edc7c0837b remove bookmark identifier from embedded links since they aren't bookmarkable without an associated taxonomy entry. 2016-02-21 18:14:28 -08:00
jeroenpraat
f535d438b2 I don't think we need redmatrix hubs (or hubs without no project name) in this list. The other way around (hubzilla in redmatrix pubsites) is no problem I think. If not agreed, please revert. 2016-02-22 03:03:32 +01:00
redmatrix
119ffd2d2d Merge pull request #290 from anaqreon/homeinstall
Added sendmail installation to .homeinstall script so that hub can se…
2016-02-22 12:43:41 +11:00
redmatrix
2c3bec3d7c Merge pull request #291 from phellmes/de201602201300
Update DE strings
2016-02-22 12:43:15 +11:00
redmatrix
f1564b4cff retry the move of AccessList to composer format (one or more third-party plugins will likely break as a result) 2016-02-21 16:49:49 -08:00
redmatrix
c9252d49f7 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-21 14:54:59 -08:00
redmatrix
411abdf8a7 fix double encoding 2016-02-21 14:54:34 -08:00
jeroenpraat
1fcc863298 There was nothing wrong with my pimped pubsites (was another problem). Took the opportunity to update schemas. Plus updated spanish and dutch strings. 2016-02-21 23:00:12 +01:00
jeroenpraat
e37c1ed981 Revert pubsites.php. There seems something wrong. Let me troubleshoot that first. 2016-02-21 20:00:09 +01:00
jeroenpraat
0c5a2925ad Pimped the pubsites page. I tried to get this into a .tpl-file, but it was to complicated for me. Pubsites page is now more narrow (fits on most devices) and location is not taking a complete column (location is almost never used). Also a fix on the auto-create-channel part on the register page. 2016-02-21 19:31:11 +01:00
Andrew Manning
272ffe6983 Renamed homeinstall config file and added check for required config parameters. Spelling corrections. 2016-02-20 14:04:11 -05:00
Andrew Manning
368bb18935 Merge branch 'master' of https://github.com/redmatrix/hubzilla into homeinstall 2016-02-20 13:53:00 -05:00
Mario Vavti
22f172d697 grid->network, whitespace and bootstrapify create button 2016-02-20 14:01:20 +01:00
phellmes
fe9abcfaae Update DE strings 2016-02-20 13:47:25 +01:00
redmatrix
dfbe2eaf98 Revert "move accesslist class to namespace"
This reverts commit a9711895cf.
2016-02-20 00:49:37 -08:00
redmatrix
a9711895cf move accesslist class to namespace 2016-02-20 19:39:54 +11:00
redmatrix
8882ffc0de ensure auto_channel_create() is executed for all workflows when UNO is set. 2016-02-19 19:21:57 -08:00
redmatrix
fdd7faab51 string update 2016-02-19 19:12:26 -08:00
redmatrix
d004017b01 issue #288 allow relative_date() to be translated into languages with more than two plural forms, such as pl. 2016-02-19 19:07:07 -08:00
Andrew Manning
f2d27d543d Added sendmail installation to .homeinstall script so that hub can send email notifications 2016-02-19 20:43:28 -05:00
redmatrix
1db3409f36 add router class 2016-02-19 16:19:15 -08:00
redmatrix
cfa2ac2d0a move dreport to zotlabs\zot namespace 2016-02-19 14:02:55 -08:00
redmatrix
ebc66d7008 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-19 13:36:48 -08:00
redmatrix
3f0eb84ecf get_feature_default() was using filtered view, preventing it from working in all cases 2016-02-19 13:34:29 -08:00
Mario Vavti
fbc6c60805 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-02-19 22:28:57 +01:00
Mario Vavti
02e82e496e pimp up mod new_channel 2016-02-19 22:28:21 +01:00
redmatrix
8e586008dd issue #287 require old password to change password 2016-02-19 13:18:51 -08:00
redmatrix
50c7c33ed1 no linefeed at end 2016-02-19 12:02:23 -08:00
redmatrix
ca52d39abe finish up the storage move 2016-02-19 11:58:17 -08:00
redmatrix
28d07fd6b2 move storage assets to zotlabs/storage 2016-02-19 00:06:10 -08:00
redmatrix
5a7b994e59 siteinfo regression with Zotlabs\Project - add an autoloader 2016-02-18 19:32:06 -08:00
redmatrix
4512a4cdd4 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-18 15:26:50 -08:00
redmatrix
342fda94e4 Provide Zotlabs\Project and System class for querying details about the project/version info. Move these out of /boot.php 2016-02-18 15:24:58 -08:00
Haakon Meland Eriksen
cc264b2d60 Merge remote-tracking branch 'upstream/master' 2016-02-18 20:33:25 +01:00
jeroenpraat
33c34984e6 h1>h2 (thanks to Mario) and help text below label on register page (like on new channel). 2016-02-18 19:48:11 +01:00
jeroenpraat
fe392a3144 Removed export temporary from UNO. Removed 'Remove Channel' from UNO, cause a UNO member has only 1 channel, so it's logical to remove the acccount (by experience on UNO hub). Styling oauth settings. 2016-02-18 16:53:04 +01:00
Wave
eeed7077ca Merge pull request #286 from wave72/master
updated Italian strings
2016-02-18 15:06:19 +01:00
Paolo Tacconi
dba1854837 updated Italian strings 2016-02-18 15:01:53 +01:00
redmatrix
c107bcfbd9 some necessary doco for set_iconfig() 2016-02-18 00:51:36 -08:00
redmatrix
912ebfebff Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-18 00:23:31 -08:00
redmatrix
76bf892f9f iconfig - add sharing variable 2016-02-18 00:20:08 -08:00
redmatrix
12a9b49c6d Merge pull request #285 from anaqreon/master
Added the installation of curl to the .homeinstall script
2016-02-18 13:53:13 +11:00
Andrew Manning
aecf9e32ef Added the installation of curl to the .homeinstall script 2016-02-17 21:15:43 -05:00
redmatrix
879bc71927 this qualifies as an interface change 2016-02-17 17:29:06 -08:00
redmatrix
4da7fcb41d schema updates for iconfig 2016-02-17 16:24:26 -08:00
redmatrix
3a84e7051e Merge branch 'iconfig' 2016-02-17 16:21:22 -08:00
redmatrix
161050df07 format atom event renderings so they are reasonably compatible with GNU-social 2016-02-17 15:56:30 -08:00
redmatrix
29284319a5 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-17 14:36:16 -08:00
redmatrix
86e73fd313 add ca help files (per Paco) 2016-02-17 14:35:45 -08:00
redmatrix
62e141a89c provide del_iconfig for completeness 2016-02-17 14:14:42 -08:00
jeroenpraat
cd8b7687c1 More clarification about privacy of private content. Changed Channel Name to simply Name when registering/creating an account or channel. First time when people see this they get confused (by experience on my hubs). This will even be more with UNO. 2016-02-17 20:47:52 +01:00
Mario Vavti
4436cd9ade Change description 2016-02-17 12:37:02 +01:00
Mario Vavti
ddbe3c7426 make always preload images before rendering the page a display setting 2016-02-17 12:32:12 +01:00
Mario Vavti
b8c7b2f81d more refinement on collapsing 2016-02-17 11:07:47 +01:00
redmatrix
696c6e88ea iconfig debugging - federation now working 2016-02-17 01:05:28 -08:00
redmatrix
a83eb14ff6 iconfig debugging 2016-02-17 00:42:51 -08:00
redmatrix
8e6dc0b66b revup 2016-02-17 00:14:49 -08:00
redmatrix
41ec5403e1 slight changes to set_iconfig - if passed an item structure only update the structure. Update the DB only if passed an item_id. This makes a clean separation of behaviour that's easy to document. One could get into some weird situations the original way which tried to update and sync both. 2016-02-16 22:53:27 -08:00
redmatrix
77eb6c5761 more work on iconfig 2016-02-16 20:49:32 -08:00
redmatrix
89c6cda303 allow admin to set and lock features when UNO is enabled 2016-02-16 18:58:29 -08:00
redmatrix
d49afead67 allow redirection to site workflow page even if auto channel create is applied 2016-02-16 18:36:29 -08:00
redmatrix
0a10215371 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-16 18:15:40 -08:00
redmatrix
64f5d80ff2 some iconfig basics 2016-02-16 18:15:19 -08:00
redmatrix
28a593e1ce revup 2016-02-16 15:19:52 -08:00
jeroenpraat
f738902107 @hubdomain also for auto-create-channel + adding css wrapper (ongoing work) 2016-02-16 21:46:24 +01:00
Mario Vavti
364972a292 Thats probably better but there are still edge cases... 2016-02-16 21:29:09 +01:00
Mario Vavti
0eb0256502 typo 2016-02-16 21:02:28 +01:00
Mario Vavti
679fb7d0d2 content -> viewport 2016-02-16 20:58:10 +01:00
Mario Vavti
45247d1595 only prefetch images on update_mode update 2016-02-16 20:53:38 +01:00
Mario Vavti
3be6ef6bfc since we preload images now we also can collapse and calculate posts above the viewport 2016-02-16 14:42:13 +01:00
redmatrix
c5827c8b4f Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-15 20:33:10 -08:00
redmatrix
bb381daae3 update fr strings from transifex 2016-02-15 20:32:42 -08:00
redmatrix
d0090f09fb Merge pull request #283 from phellmes/connedit
Add string translation to auto approval option
2016-02-16 10:33:39 +11:00
Mario Vavti
afb86aa908 clean up some unused stuff and start loading content a bit earlier 2016-02-15 22:20:55 +01:00
phellmes
3b97a9f766 Add string translation to auto approval option
Make the description for the auto-approval option translatable.
Put the switch array of that option (with another missing t-funtion)
into a $yes_no variable to be consistent with other settings pages.
2016-02-15 21:23:04 +01:00
redmatrix
d3c779f635 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-14 16:17:15 -08:00
redmatrix
4f285911f0 form cleanup (profile_photo and cover_photo), admin 'user_approve' not found, missing close div in mood_content.tpl 2016-02-14 16:15:55 -08:00
jeroenpraat
8ccddfefd9 Spanish and Dutch string update 2016-02-14 16:18:03 +01:00
redmatrix
4351a83d16 Merge pull request #282 from royalterra/master
add https://blablanet.es faillback server
2016-02-14 07:13:22 +11:00
royalterra
ddefe3b3ac add https://blablanet.es faillback server
{"version":"2016-02-12.1307H","version_tag":"1.2.2","server_role":"advanced","commit":"dd2d123","url":"https:\/\/blablanet.es","plugins":["b2tbtn","bookmarker","chess","dfedfix","diaspora","diaspost","dirstats","donar","jappixmini","libertree","ljpost","mailhost","mchat","metatag","noticias","pgpkey","pumpio","sendzid","smiley_pack","smileybutton","statistics","statistics_json","status","statusnet","twitter","wholikesme","wppost","xmpp","xmppac"],"register_policy":"REGISTER_OPEN","invitation_only":0,"directory_mode":"DIRECTORY_MODE_SECONDARY","language":"es","rss_connections":1,"expiration":0,"default_service_restrictions":false,"locked_features":[],"admin":[{"name":"BlaBlanet-ES","address":"blablanet-es@blablanet.es","channel":"https:\/\/blablanet.es\/channel\/blablanet-es"}],"site_name":"BlablaNet Espa\u00f1a  donde est\u00e1n tus amigos, Tu Red Social","platform":"BlaBlaNet","dbdriver":"mysqli","lastpoll":"2016-02-13 14:39:07","info":"","channels_total":29,"channels_active_halfyear":26,"channels_active_monthly":11,"local_posts":6600,"hide_in_statistics":0}
2016-02-13 15:16:09 +00:00
Haakon Meland Eriksen
b77c5ae61e Merge remote-tracking branch 'upstream/master' 2016-02-13 11:02:43 +01:00
redmatrix
dd2d12350c Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-12 14:03:09 -08:00
redmatrix
ade91f8190 directory modes reversed 2016-02-12 14:02:50 -08:00
Jeroen van Riet Paap
d04aef4c44 don't confuse people with matrix 2016-02-12 17:17:26 +01:00
Mario Vavti
689a6dc085 https://blablanet.es/siteinfo/json reports itself as directory_mode DIRECTORY_MODE_PRIMARY. AFAIK this should not be the case as we can only have one primary per realm. 2016-02-12 11:12:47 +01:00
Mario Vavti
0b487122f6 tryout: introduce loading of images before rendering content and provide some detailed logging in js-console 2016-02-12 11:00:50 +01:00
Haakon Meland Eriksen
ac4a8fde3a Merge remote-tracking branch 'upstream/master' 2016-02-12 06:28:40 +01:00
redmatrix
31aaf40ade Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-11 20:37:42 -08:00
redmatrix
af7c7642bb whitespace 2016-02-11 20:37:30 -08:00
redmatrix
d939173c0e Merge pull request #278 from royalterra/master
Update boot.php Add Failback Server blablanet.es
2016-02-12 14:31:29 +11:00
redmatrix
a87efe45e0 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-11 15:25:26 -08:00
redmatrix
55515a25d1 guest photo upload failing when js_upload is in use due to non-existent acl parameters 2016-02-11 15:24:21 -08:00
royalterra
7d7a254238 Merge pull request #1 from royalterra/royalterra-patch-1
Update boot.php Failback Server blablanet.es
2016-02-11 22:35:45 +00:00
royalterra
564a5ea4d5 Update boot.php Failback Server blablanet.es
This HUB is running us fallback many months us fallback server
2016-02-11 22:21:03 +00:00
Mario Vavti
d9c59a19fb update readmore.js to a more recent version 2016-02-11 13:51:37 +01:00
redmatrix
83b5adf194 feed dates are always UTC. This means we will need another mechanism to pass localised dates to items_fetch() 2016-02-10 23:05:47 -08:00
redmatrix
a26d1794fe feed dates weren't being honoured. When that was fixed they turned out to be reversed. 2016-02-10 23:00:40 -08:00
redmatrix
06a1258a9a put a sane lower time limit on content search for public feed requests 2016-02-10 19:29:00 -08:00
redmatrix
d31d3df4ea hook changes to support pubsubhubbub 2016-02-10 19:12:28 -08:00
redmatrix
91801d2e2c rev update 2016-02-10 13:55:51 -08:00
Haakon Meland Eriksen
95c686de6e Merge remote-tracking branch 'upstream/master' 2016-02-09 20:30:30 +01:00
jeroenpraat
bcb94f8238 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-02-09 16:15:49 +01:00
jeroenpraat
1d2260b44e Castellano and Nederlands string updates 2016-02-09 16:15:20 +01:00
git-marijus
81c10fc739 Merge pull request #276 from phellmes/invite
Invite module UI and strings update
2016-02-09 15:57:45 +01:00
phellmes
191a2fd5be [invite module] remove trailing spaces from translatable strings 2016-02-09 14:20:26 +01:00
phellmes
97be144913 [invite module] update UI template 2016-02-09 14:07:54 +01:00
Haakon Meland Eriksen
8c99228c8a Merge remote-tracking branch 'upstream/master' 2016-02-09 06:03:43 +01:00
redmatrix
f984502499 need to re-arrange a few things for a short vcard 2016-02-08 19:33:25 -08:00
redmatrix
315ce6d880 lots more zcard tweaks 2016-02-08 18:16:42 -08:00
redmatrix
3da8f9b13c duplicated lines in en config file 2016-02-08 14:51:03 -08:00
redmatrix
a14b87baf2 make yet another recommended security header optional - this time because of piwik. Personally I think if you want to track people you really don't understand this project and its history, but whatever.... 2016-02-08 14:48:11 -08:00
redmatrix
90fd23e0cd try that patch again 2016-02-08 14:19:49 -08:00
redmatrix
d96e985be0 Revert "sort out the well-known acme-challenge mess - at least on apache"
This reverts commit be99c7fe12.
2016-02-08 14:06:44 -08:00
redmatrix
c8788204a9 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-08 13:58:25 -08:00
redmatrix
be99c7fe12 sort out the well-known acme-challenge mess - at least on apache 2016-02-08 13:57:40 -08:00
Mario Vavti
48963f62f9 avoid collapsing only above the viewport 2016-02-08 22:19:38 +01:00
redmatrix
00ae6bdac6 a few tweaks to uno settings page to allow a default ACL to be created 2016-02-07 21:06:17 -08:00
redmatrix
a606173e07 change register workflow if uno is set 2016-02-07 20:11:08 -08:00
redmatrix
d8e6fd5df0 provide get_server_role() to abstract different roles and capabilities 2016-02-07 18:11:10 -08:00
redmatrix
ec950de205 block public was still referenced in admin/site template 2016-02-07 15:44:42 -08:00
redmatrix
62e7fa6a23 update UI template for 'mood' module 2016-02-07 15:38:54 -08:00
Haakon Meland Eriksen
2935c5fe1a Merge remote-tracking branch 'upstream/master' 2016-02-06 12:57:25 +01:00
redmatrix
021584d782 fix uno import by disabling for now 2016-02-05 23:45:16 -08:00
redmatrix
a5c111ef4f uno stuff 2016-02-05 23:13:33 -08:00
redmatrix
7868e47643 more uno groundwork 2016-02-05 13:32:15 -08:00
redmatrix
b4e3cd000f rev update 2016-02-05 00:06:35 -08:00
redmatrix
9c3568800c remove blackout setting now that the keepout plugin performs the same tasks (plus a lot more) 2016-02-04 23:59:09 -08:00
redmatrix
9cf105f8ea initial uno config 2016-02-04 23:58:31 -08:00
redmatrix
a8456782b5 will probably need this to make it work 2016-02-04 22:39:56 -08:00
Haakon Meland Eriksen
2afdba48f0 Merge remote-tracking branch 'upstream/master' 2016-02-05 06:28:52 +01:00
redmatrix
4250895243 make strict transport security header optional 2016-02-04 20:38:22 -08:00
redmatrix
bfeb89075f comment buttons hook 2016-02-04 19:06:11 -08:00
redmatrix
721f61a71d update docs 2016-02-04 18:38:36 -08:00
redmatrix
a6e5d26aea Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-02-04 18:36:36 -08:00
redmatrix
d586f64e40 update the poke page layout and UI 2016-02-04 18:35:40 -08:00
redmatrix
a0900ba052 Merge pull request #274 from mrjive/master
Small adding in search result page in /help
2016-02-05 11:11:36 +11:00
redmatrix
40b00ab362 add system black/white list for embeds ahead of personal config 2016-02-04 16:09:36 -08:00
redmatrix
18208fab84 poke basic config setting 2016-02-04 11:58:56 -08:00
Haakon Meland Eriksen
8f810a3dcf Merge remote-tracking branch 'upstream/master' 2016-02-04 06:01:15 +01:00
redmatrix
c598bbb8a9 Merge branch 'embedsec' 2016-02-03 20:33:34 -08:00
redmatrix
e6f388d869 finish moving block_public to the new security page 2016-02-03 20:32:26 -08:00
redmatrix
24e2eedd0f don't implement the default embed whitelist just yet 2016-02-03 20:29:46 -08:00
redmatrix
c75f76f740 heavy lifting on admin security page 2016-02-03 20:24:46 -08:00
redmatrix
006efbd906 change view_storage from perms_public to perms_specific in the social_private role 2016-02-03 15:44:36 -08:00
redmatrix
28386d7471 admin security page for configuring white and black lists and other security options. 2016-02-03 15:23:24 -08:00
mrjive
f9545dc359 Added section-title-wrapper and section-conent-wrapper to search result page in /help 2016-02-03 14:02:34 -08:00
mrjive
e527a52f6a Merge pull request #21 from redmatrix/master
updating from original codebase
2016-02-03 22:46:54 +01:00
redmatrix
a7ed50ecd4 more zcard tweaks 2016-02-02 19:39:47 -08:00
redmatrix
06dcaaa821 some zcard cleanup - still eneds a lot more work 2016-02-02 17:14:07 -08:00
Haakon Meland Eriksen
36ac48779c Merge remote-tracking branch 'upstream/master' 2016-02-02 17:51:34 +01:00
Wave
88669fa033 Merge pull request #271 from wave72/master
Updated Italian strings
2016-02-02 16:59:03 +01:00
Paolo Tacconi
225aa28a1b Updated Italian strings 2016-02-02 16:52:25 +01:00
Mario Vavti
f1245206ce change aside width to reflect recent widget style changes 2016-02-02 12:40:40 +01:00
redmatrix
7f453949a1 minor tweaks 2016-02-01 23:09:45 -08:00
redmatrix
38f385f67d slight formatting improvements 2016-02-01 21:23:47 -08:00
redmatrix
5f5342c0d3 adjust for folks that still have 175px profile photos 2016-02-01 21:21:22 -08:00
redmatrix
15e003f030 missing template 2016-02-01 21:14:36 -08:00
redmatrix
5edbc00865 profile embeds (still needs a bit of work) 2016-02-01 21:09:50 -08:00
redmatrix
723a49ccee add photos to the profile "likes this" dropdowns 2016-02-01 17:42:53 -08:00
redmatrix
ff487a0271 more oembed provider work - channel articles 2016-02-01 14:52:08 -08:00
mrjive
337735094b Merge pull request #20 from redmatrix/master
updating from original codebase
2016-02-01 11:25:07 +01:00
redmatrix
01b5b13475 oep for the photo top page 2016-01-31 20:44:54 -08:00
redmatrix
fd9f792f90 add album embed (embed the most recent photo with link to album) 2016-01-31 20:05:47 -08:00
redmatrix
e8ded61efb minor changes to changelog 2016-01-31 19:26:02 -08:00
redmatrix
b0e098bb68 rev update 2016-01-31 19:16:32 -08:00
redmatrix
f26c698f4a add zid 2016-01-31 16:33:25 -08:00
redmatrix
a341c889b7 add oembed provider for photos 2016-01-31 15:55:27 -08:00
Haakon Meland Eriksen
0cd82ec680 Merge remote-tracking branch 'upstream/master' 2016-01-31 10:38:19 +01:00
jeroenpraat
1f87fef968 es-es+nl strings and fixing css maintained schemas 2016-01-30 23:44:45 +01:00
Mario Vavti
c8d0a2b4bb one more css fix 2016-01-30 14:40:45 +01:00
Mario Vavti
385709853b css fixes 2016-01-30 14:26:38 +01:00
Mario Vavti
0405a49df1 fix a slight regression 2016-01-30 13:47:58 +01:00
Haakon Meland Eriksen
76484f1541 Merge remote-tracking branch 'upstream/master' 2016-01-30 12:05:49 +01:00
Mario Vavti
b6543beca2 do not make a difference if there are images or not for now 2016-01-30 01:34:27 +01:00
Mario Vavti
da198fdda5 more on collapsing 2016-01-30 01:28:01 +01:00
Mario Vavti
24f912e0b2 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-01-30 00:31:09 +01:00
Mario Vavti
d7abacb7b2 it is not perfect but it still may ease the collapsing of items above the viewport a little... 2016-01-30 00:30:49 +01:00
redmatrix
08aeeadd71 move permission check before global block check 2016-01-29 14:07:10 -08:00
redmatrix
c214692f66 add peer filtering to all .well-known services 2016-01-28 17:06:13 -08:00
redmatrix
35a9a468ce widget_item - provide ability to use the page title instead of the message_id to locate the desired item. You can use either, but the page title is often easier to use and discover. 2016-01-28 15:23:42 -08:00
mrjive
28943af494 Merge pull request #19 from redmatrix/master
updating from original codebase
2016-01-28 23:19:13 +01:00
Haakon Meland Eriksen
9abff11f86 Merge remote-tracking branch 'upstream/master' 2016-01-28 18:28:04 +01:00
redmatrix
5f1eb18da4 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-27 23:03:05 -08:00
redmatrix
ae3ca2b7df block_public_blackout setting 2016-01-27 23:02:36 -08:00
Haakon Meland Eriksen
d49c5b3d8e Merge remote-tracking branch 'upstream/master' 2016-01-28 06:24:47 +01:00
Jeroen van Riet Paap
9ea904c12d remark in the private notes encrypted
Notes are not encrypted and are readable in the database by the admin. Made a remark about that. Probably this needs to be fixed, but till than, it's better to warn people.
2016-01-28 00:21:43 +01:00
Jeroen van Riet Paap
9a4cbc05a6 no trailing slash 2016-01-27 23:48:14 +01:00
Jeroen van Riet Paap
08fbe17627 no trailing slash
it will break your system
2016-01-27 23:40:33 +01:00
Haakon Meland Eriksen
c766cf9565 Merge remote-tracking branch 'upstream/master' 2016-01-27 17:24:05 +01:00
Mario Vavti
722d7ff38d lower caution level from danger to warning for ignore button 2016-01-27 09:46:18 +01:00
redmatrix
5d6657f77a provide an icon to make 'add privacy group' stand out from the list of groups. Please revert if you think it's too messy. 2016-01-27 00:11:15 -08:00
redmatrix
d83b907cdc rename collections to privacy groups 2016-01-26 23:44:15 -08:00
redmatrix
202817740a control the generation or acceptance of directory keywords 2016-01-26 19:04:32 -08:00
redmatrix
9b08051703 bring back the ability to ignore a pending connection request without deleting it and without always having it in your face and without jumping through hoops. 2016-01-26 16:57:36 -08:00
redmatrix
9c71b74d37 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-26 15:39:25 -08:00
redmatrix
535a54040f add abook_account to cloned abook records, was missing 2016-01-26 15:38:56 -08:00
jeroenpraat
68030d12cf Linking new connection notification to pending connections (see Channel 1) and improved email notifications about new connections. Could not find a way to do this also for the generic notifications. Added hub domain of channel address on the new channel page. A few people on my hub didn't understood. This example will make it more clear. Some minor bits. 2016-01-27 00:24:05 +01:00
redmatrix
3494fddd7c change help text on other channel expiration setting to inform that there is a system limit. Ignore imported feed content that is older than expiration interval. 2016-01-26 15:12:34 -08:00
redmatrix
424af13891 fix undefined variable reference in widget_item 2016-01-26 14:14:18 -08:00
Haakon Meland Eriksen
e4674142c6 Merge remote-tracking branch 'upstream/master' 2016-01-25 07:33:18 +01:00
redmatrix
9081ddb455 don't provide notification icons on manage page for delegated channels 2016-01-24 18:36:38 -08:00
redmatrix
1ccf836ebb regression: channel name missing on delegate section of manage page 2016-01-24 18:33:02 -08:00
redmatrix
5e9e1b2c91 cleanup and add comments about what we're trying to do here 2016-01-24 15:44:16 -08:00
redmatrix
baed7d339e make exec the default for proc_run - use system.use_proc_open to use proc_open. Also prohibit delegated channels from manually invoking new_channel under the delegated account. 2016-01-24 15:20:25 -08:00
redmatrix
6759a28579 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-24 13:54:07 -08:00
redmatrix
0db2fe6e39 remote delegation issue when already logged in with different account on same site. 2016-01-24 13:53:18 -08:00
jeroenpraat
845945e70a es-es+nl string update 2016-01-24 15:31:08 +01:00
Haakon Meland Eriksen
089509ab87 Merge remote-tracking branch 'upstream/master' 2016-01-24 10:35:20 +01:00
redmatrix
ae6ae88151 update hidden_configs with proc_run_use_exec 2016-01-23 16:29:39 -08:00
redmatrix
7b73a689e1 provide option to use exec in proc_run 2016-01-23 16:25:38 -08:00
Haakon Meland Eriksen
0d119d83b0 Merge remote-tracking branch 'upstream/master' 2016-01-22 19:15:46 +01:00
Jeroen van Riet Paap
945689d01c doc 2016-01-22 16:25:00 +01:00
redmatrix
d70f69566f Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-22 02:25:05 -08:00
redmatrix
48495f41e8 provide mechanism for custom .well-known handlers and static files (e.g. for letsencypt ownership verification). Document that if you create a .well-known directory to validate a letsencrypt cert you need to remove it before installing hubzilla. We probably need a check for this in the install checklist. 2016-01-22 02:22:27 -08:00
redmatrix
47f7750f26 Merge pull request #266 from anaqreon/activitystreams
Activitystreams
2016-01-22 20:35:30 +11:00
redmatrix
81e3aa4fc8 Merge pull request #267 from bashrc/bashrc/node
Change node script types
2016-01-22 20:35:07 +11:00
Bob Mottram
8f6e01a70b Change node script types 2016-01-22 09:18:02 +00:00
Haakon Meland Eriksen
b0d5b9fd2c Merge remote-tracking branch 'upstream/master' 2016-01-22 06:37:30 +01:00
redmatrix
75468c255a Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-21 19:26:22 -08:00
redmatrix
e52f64e3d2 fix visitor photo uploads 2016-01-21 19:26:04 -08:00
redmatrix
7d7ef5ac4e add a fixme 2016-01-21 18:42:44 -08:00
Andrew Manning
b368e0a1f9 Merge branch 'master' of https://github.com/redmatrix/hubzilla into activitystreams 2016-01-21 21:40:29 -05:00
Andrew Manning
dff2cdc650 Added more ActivityStreams schema support to boot.php for games 2016-01-21 21:39:43 -05:00
redmatrix
dcaef756e7 Merge pull request #265 from bashrc/bashrc/tidying
General tidying
2016-01-22 09:57:16 +11:00
redmatrix
2be515e7bb set the actual value of the password input field to a single space on remove channel and remove account because firefox does not honour 'autocomplete="off"' and insists on filling in the password, which completely defeats the purpose of password protecting this function. We want to ensure it can only be executed by somebody who knows the password and not somebody who happens upon an unattended browser session. This space is annoying and must be removed to enter the password correctly but this appears to be the only way to provide the necessary safety for that page. Setting autocomplete to a random string as suggested by the firefox doco doesn't appear to do anything useful, as autocomplete is still performed. 2016-01-21 14:32:41 -08:00
redmatrix
699d5d1081 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-21 14:04:37 -08:00
redmatrix
8847e39fb7 regression: public forums granting send stream permissions to all connections 2016-01-21 14:03:46 -08:00
jeroenpraat
55e9bd3660 A few minor tweaks in schemas + link to login form in lostpass 2016-01-21 22:02:31 +01:00
Haakon Meland Eriksen
fb1e6ca6c1 Merge remote-tracking branch 'upstream/master' 2016-01-21 17:30:04 +01:00
Bob Mottram
88d29a7b4b Executable flash files ??? 2016-01-21 12:26:46 +00:00
Bob Mottram
cbedb50cb3 css files should not be executable 2016-01-21 12:23:49 +00:00
Bob Mottram
78b2a4af1a README files should not be executable 2016-01-21 12:23:25 +00:00
Bob Mottram
457cc48043 Type of script 2016-01-21 12:22:54 +00:00
Mario Vavti
b711c050db make contact block look widget alike 2016-01-21 11:48:10 +01:00
Mario Vavti
928f1bfa7b css cleanup 2016-01-21 10:58:38 +01:00
Mario Vavti
2b3b6268dd Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-01-21 10:42:41 +01:00
Mario Vavti
97ebf9021c bootstrapify rating and connect buttons. position the connect button more prominent right under the profile image 2016-01-21 10:42:20 +01:00
mrjive
c49e4f52ae Merge pull request #18 from redmatrix/master
updating from original codebase
2016-01-21 09:51:32 +01:00
redmatrix
1d89198444 issue #263 - account_default_channel not set to 0 when last channel of an account is removed 2016-01-20 23:16:12 -08:00
redmatrix
8c5d5b8e1c update docs - plugin listing 2016-01-19 20:51:38 -08:00
redmatrix
d3bec0b2f9 honour poco_rating_enable in item_photo_menu 2016-01-19 15:30:17 -08:00
redmatrix
c15e3de637 hook changed, up the std_version 2016-01-19 15:21:03 -08:00
redmatrix
24bffd4418 Separate item_photo_menu() into links which deal with the post and those which deal with the author. We should probably also make this info available to themes so they could for instance provide a visual separator. 2016-01-19 15:15:34 -08:00
Haakon Meland Eriksen
da6abe5462 Added auto_channel_create to config to ease registration 2016-01-19 21:06:55 +01:00
redmatrix
1e523414f8 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-18 19:08:26 -08:00
redmatrix
190f78fb5a several clarifications on hidden_configs 2016-01-18 19:07:41 -08:00
redmatrix
64acf3acbc Merge pull request #260 from HaakonME/master
Updated Hubzilla on OpenShift deploy script
2016-01-19 10:25:54 +11:00
redmatrix
a076a248bf add db_type to sample htconfig 2016-01-18 14:47:16 -08:00
redmatrix
1ca47074bc Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-18 14:42:22 -08:00
redmatrix
b380b618bc db_type not present in international config file templates issue #259 2016-01-18 14:42:03 -08:00
jeroenpraat
a036d88a4e Added a feature to hide rating buttons from a members channel and profile pages. 2016-01-18 21:37:47 +01:00
Haakon Meland Eriksen
2a57f716d3 Add config workflow_channel_next and set to channel 2016-01-18 19:57:00 +01:00
Haakon Meland Eriksen
86598705ef Add default_permissions_role social_private to autocreate a social private channel upon account registration 2016-01-18 19:47:06 +01:00
Haakon Meland Eriksen
5d24f62b95 Add Hubzilla Hubsites plugin to deploy script, change git for DeadSuperHero Hubzilla themes 2016-01-18 19:19:16 +01:00
Haakon Meland Eriksen
dd3f69eaf3 Merge remote-tracking branch 'upstream/master' 2016-01-18 07:31:37 +01:00
redmatrix
fc54f54b98 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-17 20:03:43 -08:00
redmatrix
80b88d819e doc updates 2016-01-17 20:03:33 -08:00
redmatrix
24c10ae733 Merge pull request #258 from einervonvielen/backup_to_usb_without_encryption
backup to external device now possible without encryption
2016-01-18 12:45:08 +11:00
redmatrix
3b18c82c88 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-17 16:51:06 -08:00
redmatrix
be83855acf generalise the site icon 2016-01-17 16:50:37 -08:00
redmatrix
10ed334e8c various issues from the forums 2016-01-17 16:29:32 -08:00
Haakon Meland Eriksen
c4a14c27cf Merge remote-tracking branch 'upstream/master' 2016-01-17 23:14:37 +01:00
jeroenpraat
819a331c4a update es-es and nl strings. adjusted a few matrix to grid strings 2016-01-17 20:03:26 +01:00
Einer von Vielen
9fa6593d7f backup to external device now possible without encryption. Before this
the daily backup did allow LUKS+ext4 compatible file system only.
2016-01-17 18:44:21 +01:00
Haakon Meland Eriksen
256472f9eb Merge remote-tracking branch 'upstream/master' 2016-01-17 11:26:18 +01:00
redmatrix
9b3b2efe9a call build_sync_packet() on pdledit updates 2016-01-17 01:05:32 -08:00
redmatrix
da9a8d54de minversion issue 2016-01-17 00:17:23 -08:00
Haakon Meland Eriksen
af8449cef8 Merge remote-tracking branch 'upstream/master' 2016-01-17 00:40:21 +01:00
redmatrix
0365f5d52c Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-16 14:04:14 -08:00
redmatrix
110ef6201e add $deliver flag to item_store() and item_store_update() [default true]. If false, do not send any notifications or process tag_deliver. This should avoid any network activity from happening as the result of a channel (actually item) import. Other minor fixes in the handling of the $allow_exec flag and further protecting CSS passed to widgets from rogue code and XSS. 2016-01-16 14:00:22 -08:00
Mario Vavti
0d5daea93d move dir total ratings button to the left to prevent the connect button beeing shifted on channels with ratings 2016-01-16 21:30:57 +01:00
Haakon Meland Eriksen
983e170f20 Merge remote-tracking branch 'upstream/master' 2016-01-16 13:44:23 +01:00
redmatrix
f66c6bfebf Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-15 11:59:38 -08:00
redmatrix
fe77ab4d71 minor version roll 2016-01-15 11:59:19 -08:00
mrjive
763c700372 Merge pull request #17 from redmatrix/master
updating from original codebase
2016-01-15 20:58:10 +01:00
Mario Vavti
2498df68c7 change button order for consistency 2016-01-15 13:20:45 +01:00
Mario Vavti
d36aa4fc89 provide a recent activity link in /connections 2016-01-15 12:08:04 +01:00
Mario Vavti
f4e1b2123a add an approve button to /connections and get rid of the modal popup in /connedit. for quick approval (default collection and perms etc.) we now can use the approve button in /connections else click the edit button and make changes and approval from /connedit. hope thats any better... 2016-01-15 11:28:05 +01:00
Mario Vavti
63ee0daac5 provide more contact infos and update some protocol type definitions 2016-01-15 10:42:44 +01:00
ken restivo
b58177e3c6 Use ctrl-d for multi-line messages. 2016-01-14 21:05:36 -08:00
redmatrix
f888548e0e issue with plugin loadable layouts 2016-01-14 20:51:59 -08:00
redmatrix
6ff192c4ea update widget docs with widget_cover_photo 2016-01-14 18:43:54 -08:00
redmatrix
64753effd1 cover photo fetch and widget 2016-01-14 17:25:27 -08:00
redmatrix
be9442e7b3 more cover photo work 2016-01-14 16:29:50 -08:00
Mario Vavti
ef2890fe51 this might be controversal - if approving a connection from the popup go back to connections page. if the popup is dismissed and the connection is approved from the page stay on /connedit page to be able to adjust perms etc... 2016-01-15 00:03:15 +01:00
Mario Vavti
614dcb8bce since the perms will be reset on approval better do not provide the perms tool before we approved a connection 2016-01-14 23:38:00 +01:00
Mario Vavti
3ba81c8bb6 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2016-01-14 23:23:28 +01:00
Mario Vavti
588d022fbb provide some info about our contacts - status (archived, hidden, etc.), public forum (like in directory) and show since when we are connected 2016-01-14 23:23:12 +01:00
redmatrix
96990fc1c5 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-14 11:47:23 -08:00
redmatrix
4506d80198 revision update 2016-01-14 11:45:48 -08:00
Haakon Meland Eriksen
72353bf044 Merge remote-tracking branch 'upstream/master' 2016-01-14 18:14:30 +01:00
mrjive
2696deb2a1 Merge pull request #16 from redmatrix/master
updating from original codebase
2016-01-14 18:07:56 +01:00
Mario Vavti
9f9fdc1434 bring back opacity for archived contacts 2016-01-14 14:00:02 +01:00
Mario Vavti
e2b79c34bc some work on connections 2016-01-14 13:50:47 +01:00
Mario Vavti
69573c6afe some template work on follow widget 2016-01-14 10:36:45 +01:00
mrjive
5c937c5642 Merge pull request #15 from redmatrix/master
updating from original codebase
2016-01-14 09:30:50 +01:00
redmatrix
e500a08f15 more progress on cover photo cropping and storage 2016-01-13 20:26:27 -08:00
redmatrix
82aec69302 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-13 17:32:42 -08:00
redmatrix
9584ca080c some initial work on uploading and cropping cover photos 2016-01-13 17:32:09 -08:00
Einer von Vielen
f510cd3111 . 2016-01-13 23:46:31 +01:00
Mario Vavti
e1ddee6c26 fix sharing of photo items 2016-01-13 11:23:40 +01:00
redmatrix
86b550e43e Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-13 01:36:08 -08:00
redmatrix
3bf9dc9f18 more work on auto channel creation during register 2016-01-13 01:17:02 -08:00
Mario Vavti
0ca7aa8c09 20em is to big for mobile use 2016-01-13 09:39:46 +01:00
redmatrix
58efd7553c very small tweaks to CLI plugin manager utility 2016-01-13 00:08:07 -08:00
redmatrix
0484f5b0dc Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-12 20:05:37 -08:00
redmatrix
961540160f cleanup text in INSTALL.txt 2016-01-12 20:05:16 -08:00
ken restivo
93096a9db8 Correct docs. 2016-01-12 18:51:57 -08:00
redmatrix
f757285ea8 cli utility for managing addons 2016-01-12 18:00:20 -08:00
redmatrix
baedd25309 'auto channel creation' - if the corresponding config variable is set, create a channel when an account is created.
Plugins can provide the necessary channel details (probably from an extended registration form). If no details are provided, a social (mostly public) channel will be created using the LHS of the email address and you will be directed to your channel page (unless email verification is required, in which case this step will be delayed until successful validation and login). If the reddress is already assigned a random name(1000-9999) reddress will be assigned.
2016-01-12 15:43:08 -08:00
ken restivo
bbc1a1f1fb Source the conf. 2016-01-12 13:20:37 -08:00
ken restivo
addf696db8 Add very simple, minimalist posting shell script. 2016-01-12 13:19:21 -08:00
redmatrix
9327ac0ba7 "aconfig" or account configuration storage, needed for some upcoming work. Built on top of xconfig. 2016-01-11 23:54:53 -08:00
redmatrix
a8a5cb05a7 logic reversal in version checking 2016-01-11 17:29:27 -08:00
redmatrix
bff33a98ce Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-11 16:37:29 -08:00
redmatrix
66c8658898 plugin version compatibility checking. To use, set MinVersion, MaxVersion or MinPHPversion in the plugin header block. Case is not important. We check the project versions against STD_VERSION, which should be rolled to a new y of x.x.y if the plugin interface or project code changes in an incompatible way. 2016-01-11 16:34:12 -08:00
Jeroen van Riet Paap
d6b2c8f296 Update README.md 2016-01-11 19:54:22 +01:00
Jeroen van Riet Paap
4e89895391 center 2016-01-11 19:52:12 +01:00
Jeroen van Riet Paap
0f5da31eb2 point to installation docu 2016-01-11 19:41:03 +01:00
mrjive
3206a46a92 Merge pull request #14 from redmatrix/master
updating from original codebase
2016-01-11 11:37:43 +01:00
Wave
42b35c5ac9 Merge pull request #253 from wave72/master
Italian strings updated
2016-01-11 11:02:09 +01:00
Paolo Tacconi
04180985cb Italian strings updated 2016-01-11 10:55:51 +01:00
Haakon Meland Eriksen
42433c0b44 Merge remote-tracking branch 'upstream/master' 2016-01-11 06:38:24 +01:00
redmatrix
f4d47f825d revert lost link 2016-01-10 20:38:47 -08:00
redmatrix
44137be88d Merge pull request #252 from einervonvielen/homeinstall
installation script for debian next to a router at home
2016-01-11 15:38:07 +11:00
redmatrix
a524f0c2c1 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-10 17:40:20 -08:00
redmatrix
d79d6c7055 the mail_isreply flag wasn't being set in the right cases 2016-01-10 17:39:18 -08:00
jeroenpraat
e51035ba9a String update es-es and nl. Plus some extra bits, incl .gitignore update with pageheader.html 2016-01-10 20:45:39 +01:00
Einer von Vielen
d4645ec609 Added files for installation script 2016-01-10 18:25:36 +01:00
Einer von Vielen
51f34b6b07 indexed 2016-01-10 18:24:15 +01:00
mrjive
9cbbc92062 Merge pull request #13 from redmatrix/master
updating from original codebase
2016-01-10 09:44:43 +01:00
redmatrix
23c7086605 add locked features to siteinfo to assist in debugging 2016-01-09 23:39:53 -08:00
redmatrix
b00c22916a fix relative urls on some Diaspora profile photos 2016-01-09 14:02:58 -08:00
Haakon Meland Eriksen
41057ac364 Merge remote-tracking branch 'upstream/master' 2016-01-09 18:47:52 +01:00
redmatrix
1c982315dd issue #251 2016-01-07 20:04:13 -08:00
redmatrix
bf99906386 provide admin toggle to disable delivery reports 2016-01-07 14:27:06 -08:00
redmatrix
3c88184177 optional support for public key pinning 2016-01-07 14:06:51 -08:00
redmatrix
f4968e9f45 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-07 12:48:42 -08:00
redmatrix
100412267a extra security headers, revert or fix if functionality is blocked 2016-01-07 12:47:46 -08:00
redmatrix
00b98730f7 Merge pull request #250 from wave72/master
In Hubzilla messages.po is hmessages.po
2016-01-08 06:44:29 +11:00
Wave72
242da95eed Wrong branding in Translations doc 2016-01-07 11:24:31 +01:00
Wave72
0eb5dd6d21 In Hubzilla messages.po is hmessages.po 2016-01-07 11:08:19 +01:00
mrjive
0fa34c6880 Merge pull request #12 from redmatrix/master
updating from original codebase
2016-01-07 10:47:11 +01:00
Haakon Meland Eriksen
bfe8e1e2e9 Merge remote-tracking branch 'upstream/master' 2016-01-07 00:02:40 +01:00
redmatrix
761afd029d version roll 2016-01-06 13:53:49 -08:00
redmatrix
93565ea768 features management page for hubmins 2016-01-06 13:01:28 -08:00
Haakon Meland Eriksen
1f82beb2ef Merge remote-tracking branch 'upstream/master' 2016-01-06 06:36:40 +01:00
redmatrix
c076e72cbf provide an option to toggle the view of locked features so we can use the same list in an admin feature set & lock page. 2016-01-05 20:38:32 -08:00
redmatrix
26139ee06f make 'refresh permissions' do something useful for non-zot connections 2016-01-04 23:27:06 -08:00
redmatrix
bd394ba6dc Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-04 22:13:46 -08:00
redmatrix
1f0e603992 expire delivery reports at 10 days by default instead of 30. 2016-01-04 22:12:36 -08:00
Haakon Meland Eriksen
f5c10f249c Merge remote-tracking branch 'upstream/master' 2016-01-05 06:24:43 +01:00
ken restivo
69f9842ec9 Merge pull request #249 from chris1315/patch-5
main.bb
2016-01-04 20:03:10 -08:00
Haakon Meland Eriksen
d2d71b8630 Merge remote-tracking branch 'upstream/master' 2016-01-04 20:05:59 +01:00
chris1315
ff3aa6c663 main.bb
main documentation in french
2016-01-04 19:53:55 +01:00
mrjive
dcb5f62413 Merge pull request #11 from redmatrix/master
updating from original codebase
2016-01-04 18:20:49 +01:00
Wave
c3e2505b66 Merge pull request #248 from wave72/master
Updated Italian strings
2016-01-04 14:26:09 +01:00
Paolo Tacconi
c7cc595906 Updated Italian strings 2016-01-04 14:18:52 +01:00
redmatrix
2dd9e27a44 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-04 01:20:01 -08:00
redmatrix
26ed0b0f34 version script was all screwed up 2016-01-04 01:19:40 -08:00
redmatrix
374aadc97e Provide a mechanism for a hub admin to lock features in the on or off state. Locked features will not be available in the UI on the Additional Features page to be set by members. If all features are locked, the link to the Additional Features page will not be displayed. 2016-01-04 01:02:10 -08:00
Haakon Meland Eriksen
86dd4e7ee0 Fixed deploy 2016-01-04 06:41:25 +01:00
Haakon Meland Eriksen
714a93022f Removed deploy to get from upstream 2016-01-03 23:26:00 +01:00
redmatrix
35fd21531a Merge pull request #246 from HaakonME/HaakonME-Hubzilla-on-OpenShift-Hubzilla-Chess
Hubzilla on OpenShift deploy script with Huzilla Chess
2016-01-04 08:12:16 +11:00
redmatrix
ca00ae2e23 Merge pull request #247 from chris1315/patch-3
Create about.bb
2016-01-04 08:12:02 +11:00
jeroenpraat
b8655dd3bc forgot to add this to the docu 2016-01-03 22:01:27 +01:00
jeroenpraat
9e6f43e3ff added some real examples for the default-permission-role in de docu. also updated comanche template redable and another css class to tpl file 2016-01-03 21:56:39 +01:00
chris1315
9ec258b74d Create about.bb 2016-01-03 19:45:53 +01:00
Haakon Meland Eriksen
8ca4fb3784 Add Hubzilla Chess repo to deploy script 2016-01-03 14:13:29 +01:00
Haakon Meland Eriksen
d860dd753e Hubzilla Chess - single file commit to upstream
Adding Hubzilla Chess to Hubzilla on OpenShift deploy script
2016-01-03 12:50:15 +01:00
Haakon Meland Eriksen
b4ccc62596 Add Hubzilla Chess repo to deploy script 2016-01-03 12:23:42 +01:00
mrjive
07f5bdde60 Merge pull request #10 from redmatrix/master
updating from original codebase
2016-01-03 09:52:37 +01:00
redmatrix
5b0a17359d Provide the ability for a hub admin to specify a default permissions role for the first channel created by a new account. This simplifies channel creation by restricting the available options at registration time. The restriction is not applied to any additional channels created under the same account; and in any event can be changed immediately after channel creation, if desired. 2016-01-02 23:39:57 -08:00
jeroenpraat
1ad90b8662 Update es+nl strings and added title on hover for items (needed to view titles that are cut-off) 2016-01-02 15:14:30 +01:00
redmatrix
54ceef0ba1 Merge https://github.com/redmatrix/hubzilla into pending_merge 2016-01-01 16:13:29 -08:00
redmatrix
c38edfcb32 issue #241 (redmatrix issue 405) 2016-01-01 16:12:43 -08:00
redmatrix
5b9afd7555 Merge pull request #245 from chris1315/patch-2
Create git_for_non_developers.bb
2016-01-02 07:49:00 +11:00
redmatrix
e665afcc2a Merge pull request #244 from anaqreon/anaqreon-titel-typo
Misspelled Titel
2016-01-02 07:48:42 +11:00
chris1315
b0ec0e9eac Create git_for_non_developers.bb 2016-01-01 16:24:49 +01:00
Andrew Manning
49e4016ba2 Misspelled Titel
should be Title
2016-01-01 05:53:29 -05:00
redmatrix
9ee7d60afe more issue #239 2015-12-31 15:17:12 -08:00
redmatrix
1964fa05e1 issue #239, provide 'Public' text on ACL selector when appropriate to do so. 2015-12-31 15:10:36 -08:00
redmatrix
caf3a69d99 yearly license update 2015-12-31 13:25:23 -08:00
redmatrix
769ad4a836 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-31 12:31:17 -08:00
redmatrix
062c03c9f7 comment clarification 2015-12-31 12:30:49 -08:00
redmatrix
2cf4ac26fd log API improvements and queue optimisation for singleton networks 2015-12-31 12:26:41 -08:00
jeroenpraat
405725875d nl+es-es string update 2015-12-29 22:09:47 +01:00
redmatrix
5f61f57b2c Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-29 11:16:47 -08:00
redmatrix
fbeb33479b store perms_accept on channel creation 2015-12-29 11:16:13 -08:00
redmatrix
ffd4557447 Merge pull request #238 from anaqreon/remove-bad-url
Removed defunct URL from old auto-update idea
2015-12-28 18:12:50 +11:00
redmatrix
cf5df259e5 refresh issue 2015-12-27 21:08:28 -08:00
Andrew Manning
3d6359f2e7 Removed defunct URL from old auto-update idea 2015-12-26 16:20:56 -05:00
redmatrix
5a229234e7 Set accept permissions to that of role so if you change to a custom role you don't start with nothing. 2015-12-25 15:56:29 -08:00
redmatrix
b1a77b2235 don't send wall-post notifications when creating webpages on another channel 2015-12-25 14:59:46 -08:00
redmatrix
6db6fef29f spelling 2015-12-25 14:56:06 -08:00
redmatrix
31fbd19c86 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-25 14:32:16 -08:00
redmatrix
a085f4df7f regression: default inherited permission was not being set for a connection if the permission was 'inherited'. We need to set these so that if somebody changes the top level permissions they don't have to go back and manually edit every connection to allow/deny what used to be an automatic inherited setting. 2015-12-25 14:25:58 -08:00
jeroenpraat
cd2c6779b7 update es-es strings 2015-12-25 17:37:05 +01:00
redmatrix
d39cd088a1 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-24 14:41:47 -08:00
redmatrix
e98fcf68f0 issue #235 2015-12-24 14:41:18 -08:00
jeroenpraat
7d5e066056 After reading and talking with experts I came to the conclusion that es-es and es-419 (and such) dont differ that much. Latin-American Spanish (es-419) is a good idea, but we are not in a rush. So linked es to es-es. That's the proper way to do. See also https://github.com/redmatrix/hubzilla/issues/234#issuecomment-167117960 2015-12-24 15:29:52 +01:00
jeroenpraat
ba920260b8 reverted my previous commit. this is going to be fixed remotely upstream. Meanwhile es points to .es-419. See https://github.com/redmatrix/hubzilla/issues/234#issuecomment-166961958. 2015-12-23 19:18:46 +01:00
jeroenpraat
2988d96cf0 Spanish language codes. See issue #234 2015-12-23 16:41:22 +01:00
redmatrix
36717e5f32 start on refactor of plugin/theme/widget info block parsing 2015-12-22 19:53:00 -08:00
jeroenpraat
4dff54bcb8 update es+nl strings 2015-12-22 19:29:52 +01:00
redmatrix
7a9fe0907a make the queue api accessible to addons 2015-12-21 17:00:42 -08:00
redmatrix
bc5a675cdf Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-20 14:57:01 -08:00
redmatrix
f23e8f8d41 merge hell 2015-12-20 14:55:43 -08:00
redmatrix
61fa97baab Merge branch 'HaakonME-master' 2015-12-20 14:54:08 -08:00
redmatrix
047163b884 Merge pull request #232 from wave72/master
Added 'invitation_only' to site info
2015-12-21 06:14:33 +11:00
Haakon Meland Eriksen
6409237b29 Updated Norwegian strings for Hubzilla 2015-12-20 14:42:14 +01:00
wave72
598a428c6b Added 'invitation_only' to site info 2015-12-20 14:41:49 +01:00
Haakon Meland Eriksen
1cfb83f003 Merge remote-tracking branch 'upstream/master' 2015-12-20 14:09:30 +01:00
Wave
2aad4c2cf9 Merge pull request #4 from redmatrix/master
Merge master into dev branch
2015-12-20 10:20:36 +01:00
Wave
e2692a4baa Merge pull request #230 from wave72/master
Updated Italian strings
2015-12-20 10:17:55 +01:00
wave72
474a1267d7 Updated Italian strings 2015-12-20 10:08:43 +01:00
redmatrix
ed5ca9e4cc use realpath to bypass symlinks and check actually directory 2015-12-18 14:55:19 -08:00
redmatrix
8d61efa0e8 allow widget 'packages' as well as individual files 2015-12-18 14:10:06 -08:00
redmatrix
b816a575eb Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-18 13:46:38 -08:00
redmatrix
a99d28dea9 sql delete with limit 2015-12-18 13:46:03 -08:00
Haakon Meland Eriksen
628e565a6c Merge remote-tracking branch 'upstream/master' 2015-12-18 16:04:07 +01:00
Mario Vavti
84bf705811 update smarty to 3.1.28 stable 2015-12-18 11:33:34 +01:00
Haakon Meland Eriksen
a721f39945 Commented out extra addons, themes etc. 2015-12-18 07:24:05 +01:00
redmatrix
1b9722c65a loop detection 2015-12-17 18:16:46 -08:00
redmatrix
62a60e5542 more work on media uploads via api 2015-12-17 16:22:13 -08:00
redmatrix
539d06f02d Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-17 14:27:07 -08:00
redmatrix
9c23fe5ab6 issue #228 2015-12-17 14:26:42 -08:00
Mario Vavti
f78e9001f3 fix search item attachment rendering 2015-12-17 19:39:26 +01:00
zzottel
dee1841394 Merge pull request #227 from zzottel/master
add forgotten German docs
2015-12-17 14:33:38 +01:00
zottel
a5201a90e8 Merge remote-tracking branch 'upstream/master' 2015-12-17 14:30:34 +01:00
zottel
5f5e4ee6b9 add forgotten German docs 2015-12-17 14:29:35 +01:00
zzottel
cf6519da99 Merge pull request #226 from zzottel/master
help files
2015-12-17 14:28:15 +01:00
zottel
63eaf643a8 small fixes to English docs 2015-12-17 14:27:13 +01:00
zottel
a57a3c709e reorganize German docs to fit the new docs structure
fix mentions of RedMatrix
2015-12-17 14:25:16 +01:00
redmatrix
bcebd1d5b9 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-16 22:47:23 -08:00
redmatrix
4cacfe59bd queue/notification/delivery refactor continued 2015-12-16 22:42:33 -08:00
redmatrix
f3ad7b9a16 Merge pull request #225 from zzottel/master
help files
2015-12-17 10:39:49 +11:00
redmatrix
b909c878b1 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-16 14:49:20 -08:00
redmatrix
b155f2260f some notifier optimisations. Also put a fixme on the invite total generations for new accounts, which is incorrect and now commented out. 2015-12-16 14:47:30 -08:00
zottel
63256bc9b2 small fixes in English help files 2015-12-16 17:00:05 +01:00
zottel
87519e107a updates to some German help files 2015-12-16 16:59:17 +01:00
zzottel
a38710aa4e Merge pull request #224 from zzottel/master
update to German strings
2015-12-16 14:01:33 +01:00
zottel
020fea3031 update to German strings 2015-12-16 14:00:23 +01:00
zzottel
b4102489aa Merge pull request #223 from zzottel/master
remove directory red.zottel.red, add hubzilla.zottel.net instead
2015-12-16 12:32:17 +01:00
Wave
871ee0f571 Merge pull request #222 from wave72/master
Updated Italian strings
2015-12-16 09:13:40 +01:00
zottel
f0d90005ea remove directory fallback server red.zottel.red, add hubzilla.zottel.net instead 2015-12-16 09:06:20 +01:00
Paolo Tacconi
933e105f32 Updated Italian strings 2015-12-16 09:00:27 +01:00
redmatrix
9b4e6e1ec0 some more minor api tweaks 2015-12-15 20:21:40 -08:00
redmatrix
46e4d2d573 bring back the schemaspy makefile 2015-12-15 20:00:48 -08:00
redmatrix
2aa3acae6b remove deprecated table 2015-12-15 19:46:24 -08:00
redmatrix
8514789da9 additional fix for the array_key_exists message in #221 2015-12-15 17:50:14 -08:00
redmatrix
20dcf37976 issue #221 2015-12-15 17:42:49 -08:00
redmatrix
38d513181d Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-15 15:17:39 -08:00
redmatrix
f121b74bec enhance whitespace 2015-12-15 15:17:10 -08:00
redmatrix
cb8cccc537 fix typos before merging 2015-12-15 15:13:16 -08:00
redmatrix
2924b9182e revise the photo activity a bit so that we always have a valid activity body. Several network connectors can get empty posts or posts that don't contain any reference whatsoever to the actual photo. Since this can cause duplicate images on our own site, just provide the activity summary and any included body text to the activity by default. Provide a function to enhance this activity with an actual photo which can be applied on demand for any network connectors that desire it. Otherwise they'll just get a link to the photo in the activity statement - which is better than an empty post. Have applied this "add actual photo to the post" function to both Diaspora and RSS feeds. Also provide the album as the activity target. 2015-12-15 15:01:54 -08:00
jeroenpraat
5a59cd9b8c Invitation only added to the admin site page. Plus css wrapper class to docu search. 2015-12-15 21:00:40 +01:00
redmatrix
ba463afbdc even more queue api 2015-12-15 00:42:19 -08:00
redmatrix
6f2a5117dc more queue api 2015-12-15 00:04:30 -08:00
redmatrix
b13241564b more work on queue api 2015-12-14 22:44:05 -08:00
redmatrix
76816de3aa simplify queue insertion for normal items 2015-12-14 20:49:12 -08:00
redmatrix
49108c230b regenerate the item body for linked photo items that now have no body to provide legal activities when going to other networks. Remove the signature since the signed text was an empty string and we've just replaced it with content that will not verify. 2015-12-14 17:58:39 -08:00
redmatrix
b32bba47c8 set following to false 2015-12-14 17:25:40 -08:00
Haakon Meland Eriksen
3b1ab5e79c Merge remote-tracking branch 'upstream/master' 2015-12-14 18:55:43 +01:00
redmatrix
dcf7946673 revert include/photos.php:L380 2015-12-14 02:34:18 -08:00
redmatrix
fdd2da905a more work on api media uploads 2015-12-13 19:15:42 -08:00
redmatrix
2cceca49e9 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-13 15:37:26 -08:00
redmatrix
bb0e4044bf remove the unqualified "OAuth" namespace from the project. We need to reference either OAuth1 or OAuth2. 2015-12-13 15:35:45 -08:00
jeroenpraat
7244dfce1d Typos 2015-12-12 17:32:29 +01:00
jeroenpraat
fb5ac37ca2 That script is taken from someone else without any contribution (http://blog.strictly-software.com/2013/07/apache-performance-tuning-bash-script.html). Also the English is very bad. Anyway, I've replaced it with some general tips that all web admins should know. 2015-12-12 17:30:02 +01:00
jeroenpraat
f0a588547d Merge branch 'master' of https://github.com/redmatrix/hubzilla 2015-12-12 17:02:01 +01:00
jeroenpraat
04d3ac9aaf es+nl strings update 2015-12-12 17:01:43 +01:00
Haakon Meland Eriksen
565126a888 Hubzilla textbox - promoting Hubzilla features in jot.tpl - third version 2015-12-12 10:00:15 +01:00
redmatrix
395268da22 a couple of api improvements 2015-12-11 21:10:20 -08:00
redmatrix
ac3075bef7 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-11 17:01:23 -08:00
redmatrix
1f4c596841 add deprecated update_with_media endpoint 2015-12-11 17:00:45 -08:00
redmatrix
6613275cc2 Merge pull request #215 from royalterra/master
Add Link and extra Doc to Apache Configuration
2015-12-12 09:15:24 +11:00
Haakon Meland Eriksen
e7d9863432 Hubzilla textbox - promoting Hubzilla features in jot.tpl - third version 2015-12-11 19:40:09 +01:00
Haakon Meland Eriksen
b9af0645c2 Hubzilla textbox - promoting Hubzilla features in jot.tpl - third version 2015-12-11 19:34:29 +01:00
redmatrix
9fb7a12849 incorrect obj_type on several items 2015-12-11 02:52:43 -08:00
royalterra
4633273279 Update INSTALL.txt
Add Link to ApacheTune for configure mod Prefork
2015-12-11 09:49:14 +00:00
royalterra
d0482133a5 Update INSTALL.txt 2015-12-11 09:48:04 +00:00
royalterra
4ff31d0a41 Merge pull request #1 from redmatrix/master
merge branches
2015-12-11 09:39:01 +00:00
redmatrix
f73c82632f some minor cleanup - change the default of the discover tab (public stream access) 2015-12-10 19:18:55 -08:00
redmatrix
8389d8677d some major cleanup of api authentication stuff - still needs much more and this still may not solve #206 2015-12-10 16:39:46 -08:00
redmatrix
7fa944ed95 don't spit out sabre xml on permission denied exceptions, just provide a 401 2015-12-10 15:13:10 -08:00
redmatrix
2340092008 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-10 14:44:37 -08:00
jeroenpraat
6cd3296c08 Missing underscores in doc 2015-12-10 23:32:25 +01:00
Haakon Meland Eriksen
d86bc0b6cf Hubzilla textbox - promoting Hubzilla features in jot.tpl - third version 2015-12-10 20:43:32 +01:00
Haakon Meland Eriksen
e01d4f289b Hubzilla textbox - promoting Hubzilla features in jot.tpl - third version 2015-12-10 07:27:42 +01:00
redmatrix
8e1e301764 refactor a few more redundant returns 2015-12-09 21:03:29 -08:00
redmatrix
bd37f59829 simplify magic-auth - a lot... Would be even simpler if we didn't need to provide remote debugging, which takes up about half the code. But we need that because nobody wants to try and debug this shit by asking somebody at the other end to report what's in their logfile. We've tried this repeatedly. The only thing we can do is bring back all the debugging data so you can look at it yourself. 2015-12-09 20:51:00 -08:00
redmatrix
72edc9cd6c start working on the singleton setting 2015-12-09 18:30:30 -08:00
redmatrix
93123e1fa8 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-09 14:56:27 -08:00
redmatrix
4b6dcbb057 provide paths for include files 2015-12-09 14:56:08 -08:00
jeroenpraat
47f7165b07 Some work on the login, register and default home page. Mostly neatly centering things on different viewport widths. Bluegrid schema updated. 2015-12-09 23:41:37 +01:00
redmatrix
ae2c0e6552 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-09 11:51:55 -08:00
redmatrix
200eabe052 add empty arg 2015-12-09 11:51:31 -08:00
redmatrix
5042200492 Merge pull request #212 from msooon/master
Let’s Encrypt support
2015-12-10 06:24:30 +11:00
jeroenpraat
2e73e6bfb6 Fix #109. 2015-12-09 14:37:14 +01:00
msooon
c1d10bbbcb Merge pull request #1 from msooon/Lets-encrypt-support
Let’s Encrypt added
2015-12-09 12:21:17 +01:00
msooon
746acc21f7 Let’s Encrypt added 2015-12-09 10:54:48 +01:00
msooon
f5226a748f Let’s Encrypt added 2015-12-09 10:48:41 +01:00
Haakon Meland Eriksen
6a3995014e Hubzilla textbox - promoting Hubzilla features in jot.tpl - third version 2015-12-09 07:38:58 +01:00
Haakon Meland Eriksen
534a537319 Hubzilla textbox - promoting Hubzilla features in jot.tpl - third version 2015-12-09 07:31:18 +01:00
Haakon Meland Eriksen
10eefc4eed Hubzilla textbox - promoting Hubzilla features in jot.tpl - second version 2015-12-09 07:28:55 +01:00
Haakon Meland Eriksen
3d4b3b6a92 Hubzilla textbox - promoting Hubzilla features in jot.tpl 2015-12-09 07:19:31 +01:00
redmatrix
0f4ceedbb4 remove duplicated code 2015-12-08 20:47:55 -08:00
redmatrix
656e5fd052 use killme() instead of die() so that any sessions are closed cleanly. 2015-12-08 20:42:46 -08:00
redmatrix
5735cad457 remove extra debug logging and ensure we don't try to authenticate without a hubloc 2015-12-08 19:43:49 -08:00
redmatrix
648f972cf0 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-08 18:32:05 -08:00
redmatrix
baab9b6fbc more libzot stuff 2015-12-08 18:31:33 -08:00
jeroenpraat
60b0f9af90 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2015-12-09 01:39:20 +01:00
jeroenpraat
9d04406f9a First part of fix for issue #109 2015-12-09 01:39:02 +01:00
redmatrix
29ac533cc9 remove some unused stuff 2015-12-08 16:32:06 -08:00
redmatrix
79340c5147 change to fallback server list 2015-12-08 11:08:00 -08:00
redmatrix
b9f5076cfc move the diaspora templates out of core (except for diaspora_vcard, which is still stuck here for the present time) 2015-12-07 19:17:40 -08:00
redmatrix
241607e7d7 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-07 16:15:52 -08:00
redmatrix
bd7d851758 a loose end 2015-12-07 16:11:39 -08:00
redmatrix
5de1a1ce10 extra paren removed 2015-12-07 16:06:43 -08:00
redmatrix
8b974f8f74 abstract the message handlers 2015-12-07 16:01:54 -08:00
jeroenpraat
96d94551f9 update es+nl 2015-12-07 21:10:36 +01:00
Mario Vavti
ba8d9c0f0b Merge branch 'master' of https://github.com/redmatrix/hubzilla 2015-12-07 20:28:51 +01:00
Mario Vavti
68cbebe1a5 mod_mitem.js is obsolete 2015-12-07 20:28:17 +01:00
Mario Vavti
0174cb10ae fix issue #210 2015-12-07 19:11:32 +01:00
Mario Vavti
293df6308c some style.css janitor work 2015-12-07 18:57:03 +01:00
Mario Vavti
af29822f04 override bs default margin 2015-12-07 15:45:21 +01:00
Mario Vavti
0df4f9c114 change album_id logic to make it work with ajax calls 2015-12-07 13:27:35 +01:00
Mario Vavti
69c9f4588c make justify gallery work with more than one albums per page (eg album widget) 2015-12-07 12:13:51 +01:00
redmatrix
53627c89a7 Merge branch 'dev' 2015-12-06 20:50:02 -08:00
redmatrix
f7f0d2b265 provide plugin hooks for blacklist checking functions. 2015-12-06 20:45:21 -08:00
redmatrix
2d799f2c11 remove duplicated code 2015-12-06 19:59:46 -08:00
redmatrix
aa5b7eb98a minor optimisation 2015-12-06 19:48:46 -08:00
redmatrix
1c22e8ae7e whitespace 2015-12-06 19:32:39 -08:00
redmatrix
4d301bc5a6 comment order 2015-12-06 19:29:01 -08:00
redmatrix
4ccd9ae6da start of v4 2015-12-06 19:16:38 -08:00
Mario Vavti
c8c9916b59 Merge branch 'master' of https://github.com/redmatrix/hubzilla 2015-12-07 00:01:03 +01:00
Mario Vavti
5490919557 css fixes for blockquote and code (use same padding) 2015-12-07 00:00:47 +01:00
redmatrix
3f920da413 update error 2015-12-06 14:25:47 -08:00
redmatrix
2393db3943 Merge branch 'dev' 2015-12-06 14:24:18 -08:00
redmatrix
a88ec1b1af Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-06 14:22:55 -08:00
redmatrix
553b3a5c6c version 2015-12-06 14:22:36 -08:00
Mario Vavti
a6cb25020b add missing smarty files 2015-12-06 23:12:37 +01:00
Mario Vavti
26c465ad0c update smarty to 3.1.28-dev which fixes a bug where changes in a template are only visible on the second pageload which is annoying for developing 2015-12-06 21:09:58 +01:00
Mario Vavti
f2d7083183 remove more unneeded smarty files 2015-12-06 20:25:42 +01:00
Mario Vavti
ef09a29854 remove composer release notes 2015-12-06 20:14:12 +01:00
Mario Vavti
c23ce16caf update smarty library - seems to bring some performance improvement 2015-12-06 20:12:05 +01:00
Mario Vavti
78a70fed2f fix css issue in directory 2015-12-06 16:37:57 +01:00
redmatrix
9dfe5dee64 change text "Red developers" in update failed email 2015-12-05 13:56:32 -08:00
redmatrix
36ef1d1bc6 move the instance stuff to abook where it belongs 2015-12-05 13:24:58 -08:00
redmatrix
10db51e6c2 Merge branch 'master' into dev 2015-12-05 12:48:46 -08:00
redmatrix
61aa33af1d Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-05 12:41:08 -08:00
redmatrix
d8dc055dce version and string update 2015-12-05 12:40:35 -08:00
redmatrix
ce686d2c06 Merge pull request #209 from HaakonME/master
Updated Norwegian strings for Hubzilla 1.0
2015-12-06 07:35:31 +11:00
Haakon Meland Eriksen
7119976199 Merge remote-tracking branch 'upstream/master' 2015-12-05 11:26:07 +01:00
Haakon Meland Eriksen
dd7edc8ced Updated Norwegian translation 2015-12-05 11:25:36 +01:00
redmatrix
4428f70ea2 Merge pull request #208 from anaqreon/mail-text-height
Enlarge the default mail composition text area.
2015-12-05 07:47:15 +11:00
Andrew Manning
0bb7589418 Enlarge the default mail composition text area. 2015-12-04 15:29:57 -05:00
mrjive
0513463256 Merge pull request #9 from redmatrix/master
updating from original codebase
2015-12-04 10:32:14 +01:00
Mario Vavti
8a9d743f6f fix rendering of unseen forum posts count 2015-12-04 10:17:13 +01:00
redmatrix
4cab74c18c use the channel blacklist for items and mail, still todo: directory and stuff 2015-12-03 21:05:48 -08:00
redmatrix
615c97132d add hubzilla.nl as fallback 2015-12-03 19:18:12 -08:00
redmatrix
4b707db4b3 Merge https://github.com/redmatrix/hubzilla into pending_merge 2015-12-03 18:28:32 -08:00
redmatrix
70c5f347c4 remove non-working directory server from the project fallback list. 2015-12-03 18:27:49 -08:00
ken restivo
5217d89543 srand() is for seeding the PRNG. You want rand() here. 2015-12-03 18:21:25 -08:00
redmatrix
ca55bbdaed use the std_version where applicable instead of matching to the git. 2015-12-03 17:09:05 -08:00
Haakon Meland Eriksen
c363fc71eb Merge remote-tracking branch 'upstream/master' 2015-12-03 18:14:52 +01:00
Haakon Meland Eriksen
b96f09bb3a Merge remote-tracking branch 'upstream/master' 2015-12-01 00:35:01 +01:00
Haakon Meland Eriksen
519862115c Merge remote-tracking branch 'upstream/master' 2015-11-29 11:56:47 +01:00
Haakon Meland Eriksen
4d97ea106c Resolving merge conflict 2015-11-29 11:55:39 +01:00
Haakon Meland Eriksen
8cf6b4064f My version of jot.tpl 2015-11-28 16:44:02 +01:00
Haakon Meland Eriksen
17907f11a3 Merge remote-tracking branch 'upstream/master'
Conflicts:
	include/datetime.php
	include/text.php
	mod/events.php
	version.inc
	view/css/mod_events.css
	view/theme/redbasic/css/style.css
	view/tpl/event_head.tpl
	view/tpl/events-js.tpl
	view/tpl/jot.tpl
2015-11-28 16:26:24 +01:00
Haakon Meland Eriksen
cb7df797e1 Removed my version of jot.tpl 2015-11-28 16:23:17 +01:00
Haakon Meland Eriksen
2b2723cb74 Merge remote-tracking branch 'upstream/master' 2015-11-24 07:23:43 +01:00
Haakon Meland Eriksen
7338649fa5 Merge remote-tracking branch 'upstream/master' 2015-11-23 14:16:14 +01:00
Haakon Meland Eriksen
e60f527cb0 Documenting the need to change database server address from 127.0.0.1 to localhost when installing Hubzilla on OpenShift with the deploy script 2015-11-22 10:50:17 +01:00
Haakon Meland Eriksen
b5a5a91b13 Merge remote-tracking branch 'upstream/master' 2015-11-22 01:56:25 +01:00
Haakon Meland Eriksen
9ba1b8d720 Merge remote-tracking branch 'upstream/master' 2015-11-21 17:18:44 +01:00
Haakon Meland Eriksen
bd45bb3ad3 Merge remote-tracking branch 'upstream/master' 2015-11-21 12:17:38 +01:00
Haakon Meland Eriksen
6942c715d0 Merge remote-tracking branch 'upstream/master' 2015-11-21 00:08:17 +01:00
Haakon Meland Eriksen
de1b3d5113 Space between Preview and Submit in jot.tpl 2015-11-20 21:15:12 +01:00
Haakon Meland Eriksen
830b01bd2a Space between Preview and Submit in jot.tpl 2015-11-20 21:12:09 +01:00
Haakon Meland Eriksen
90187eae37 Merge remote-tracking branch 'upstream/master' 2015-11-20 19:51:57 +01:00
Haakon Meland Eriksen
3b7b3ef2bb Rearranging buttons 2015-11-20 07:38:59 +01:00
Haakon Meland Eriksen
b6e4611a91 Rearranging buttons 2015-11-20 07:35:43 +01:00
Haakon Meland Eriksen
2929bb672a Rearranging buttons 2015-11-20 07:29:45 +01:00
Haakon Meland Eriksen
a4765bf954 Rearranging buttons 2015-11-20 07:03:36 +01:00
Haakon Meland Eriksen
0c2045beff Rearranging buttons 2015-11-20 06:52:35 +01:00
Haakon Meland Eriksen
22f6687f44 Merge remote-tracking branch 'upstream/master' 2015-11-20 06:27:46 +01:00
Haakon Meland Eriksen
059886a1e4 Merge remote-tracking branch 'upstream/master' 2015-11-19 18:44:33 +01:00
Haakon Meland Eriksen
cd49ec92e3 Merge remote-tracking branch 'upstream/master' 2015-11-19 06:36:06 +01:00
Haakon Meland Eriksen
7b4cfffc03 Merge remote-tracking branch 'upstream/master' 2015-11-19 00:00:35 +01:00
Haakon Meland Eriksen
33258803ea Merge remote-tracking branch 'upstream/master' 2015-11-18 16:48:56 +01:00
Haakon Meland Eriksen
0d232c612b Merge remote-tracking branch 'upstream/master' 2015-11-18 06:48:29 +01:00
Haakon Meland Eriksen
545dc5cf65 Merge remote-tracking branch 'upstream/master' 2015-11-18 01:52:11 +01:00
Haakon Meland Eriksen
c545ada746 Merge remote-tracking branch 'upstream/master' 2015-11-17 16:49:11 +01:00
Haakon Meland Eriksen
69487389d3 Merge remote-tracking branch 'upstream/master' 2015-11-16 06:42:08 +01:00
Haakon Meland Eriksen
fd5d1416d9 Merge remote-tracking branch 'upstream/master' 2015-11-15 00:27:23 +01:00
Haakon Meland Eriksen
6bdde985ce Merge remote-tracking branch 'upstream/master' 2015-11-14 08:32:37 +01:00
Haakon Meland Eriksen
9d6a4c1d05 Reorder buttons HME 2015-11-13 19:44:42 +01:00
Haakon Meland Eriksen
94bef08f15 Adding original jot.tpl from GitHub 2015-11-13 18:32:25 +01:00
Haakon Meland Eriksen
0178840c19 Merge remote-tracking branch 'upstream/master' 2015-11-13 16:45:31 +01:00
Haakon Meland Eriksen
d04c73ae00 Reorder buttons 2015-11-13 16:31:48 +01:00
Haakon Meland Eriksen
495f21c08c Reverted changes - got white screen 2015-11-13 07:36:32 +01:00
Haakon Meland Eriksen
d238cbea19 Regrouped post buttons 2015-11-13 07:03:30 +01:00
Haakon Meland Eriksen
921a2e0dc4 Regrouped post buttons 2015-11-13 00:07:09 +01:00
Haakon Meland Eriksen
ba84d6ff7c Regrouped post buttons 2015-11-12 21:11:47 +01:00
Haakon Meland Eriksen
d786502f19 Regrouped post buttons 2015-11-12 20:44:41 +01:00
Haakon Meland Eriksen
63063450b3 Merge remote-tracking branch 'upstream/master' 2015-11-12 07:46:29 +01:00
Haakon Meland Eriksen
90463ee67d Make upload and encrypt easier on phones by editing jot.tpl 2015-11-12 07:45:37 +01:00
Haakon Meland Eriksen
e26b558e53 Promoted upload of images and encryption 2015-11-11 23:55:05 +01:00
Haakon Meland Eriksen
85e5cd7f98 Rearranged comment buttons back 2015-11-11 23:43:41 +01:00
Haakon Meland Eriksen
1d8cac6e73 Rearranged comment buttons 2015-11-11 23:31:18 +01:00
mrjive
53a796afcc Merge pull request #8 from redmatrix/master
get fresh code from HZ base
2015-11-11 16:51:48 +01:00
mrjive
a4c3058f84 Merge pull request #7 from redmatrix/master
updating from original codebase
2015-10-26 21:55:47 +01:00
mrjive
32522b61f2 Merge pull request #6 from redmatrix/master
updating from original codebase
2015-10-02 09:45:03 +02:00
mrjive
11c1573b55 Merge pull request #5 from redmatrix/master
updating from original codebase
2015-09-29 08:01:51 +02:00
mrjive
006ca4421a Merge pull request #4 from redmatrix/master
updating from original codebase
2015-09-23 17:13:55 +02:00
mrjive
5ec3d3e36d Merge pull request #3 from redmatrix/master
updating from original codebase
2015-09-22 13:11:54 +02:00
mrjive
49d11ed9f8 Merge pull request #2 from redmatrix/master
get fresh code from HZ base
2015-09-21 15:41:17 +02:00
mrjive
024af91df8 Merge pull request #1 from redmatrix/master
updating from original codebase
2015-09-17 09:27:13 +02:00
2768 changed files with 294213 additions and 318341 deletions

2
.gitignore vendored
View File

@@ -27,6 +27,8 @@ custom/
apps/ apps/
# default startpage # default startpage
home.html home.html
# page header plugin
pageheader.html
# Ignore site TOS # Ignore site TOS
doc/SiteTOS.md doc/SiteTOS.md
# themes except for redbasic # themes except for redbasic

164
.homeinstall/README.md Normal file
View File

@@ -0,0 +1,164 @@
# Hubzilla at Home next to your Router
Run hubzilla-setup.sh for an unattended installation of hubzilla.
The script is known to work with Debian 8.3 stable (Jessie)
+ Home-PC (Debian-8.3.0-amd64)
+ DigitalOcean droplet (Debian 8.3 x64 / 512 MB Memory / 20 GB Disk / NYC3)
# Step-by-Step Overwiew
## Preconditions
Hardware
+ Internet connection and router at home
+ Mini-pc connected to your router
+ USB drive for backups
Software
+ Fresh installation of Debian on your mini-pc
+ Router with open ports 80 and 443 for your Debian
## The basic steps (quick overview)
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
+ Log on to your new debian (server)
- apt-get install git
- mkdir -p /var/www/html
- cd /var/www/html
- git clone https://github.com/redmatrix/hubzilla.git .
- 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
- hubzilla-setup.sh as root
- ... wait, wait, wait until the script is finised
- reboot
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
# Step-by-Step in Detail
## Preparations Hardware
### Mini-PC
### Recommended: USB Drive for Backups
The installation will create a daily backup.
If the backup process does not find an external device than the backup goes to
the internal disk.
The USB drive must be compatible with an encrpyted filesystem LUKS + ext4.
## Preparations Software
### Install Debian Linux on the Mini-PC
Download the stable Debian at https://www.debian.org/
Create bootable USB drive with Debian on it. You could use the programm
unetbootin, https://en.wikipedia.org/wiki/UNetbootin
Switch of your mini pc, plug in your USB drive and start the mini pc from the
stick. Install Debian. Follow the instructions of the installation.
### Configure your Router
Open the ports 80 and 443 on your router for your Debian
## Preparations Dynamic IP Address
Your Hubzilla must be reachable by a domain that you can type in your browser
cooldomain.org
You can use subdomains as well
my.cooldomain.org
There are two way to get a domain
- buy a domain (recommended) or
- register a free subdomain
### Method 1: Get yourself an own Domain (recommended)
...for example at selfHOST.de
### Method 2 Register a (free) Subdomain
Register a free subdomain for example at
- freeDNS
- selfHOST
WATCH THIS: A free subdomain is not the prefered way to get a domain name. Why?
Let's encrpyt issues a limited number of certificates each
day. Possibly other users of this domain will try to issue a certificate
at the same day as you do. So make sure you choose a domain with as less subdomains as
possible.
## Install Hubzilla on your Debian
Login to your debian
(Provided your username is "you" and the name of the mini pc is "debian". You
could take the IP address instead of "debian")
ssh -X you@debian
Change to root user
su -l
Install git
apt-get install git
Make the directory for apache and change diretory to it
mkdir /var/www
cd /var/www/
Clone hubzilla from git ("git pull" will update it later)
git clone https://github.com/redmatrix/hubzilla html
Change to the install script
cd html/.homeinstall/
Copy the template file
cp hubzilla-config.txt.template hubzilla-config.txt
Change the file "hubzilla-config.txt". Read the instructions there and enter your values.
nano hubzilla-config.txt
Run the script
./hubzilla-setup.sh
Wait... The script should not finish with an error message.
In a webbrowser open your domain.
Expected: A test page of hubzilla is shown. All checks there shoulg be
successfull. Go on...
Expected: A page for the Hubzilla server configuration shows up.
Leave db server name "127.0.0.1" and port "0" untouched.
Enter
- DB user name = hubzilla
- DB pass word = This is the password you entered in "hubzilla-config.txt"
- DB name = hubzilla
Leave db type "MySQL" untouched.
Follow the instructions in the next pages.

View File

@@ -0,0 +1,177 @@
###############################################
### MANDATORY - database password #############
#
# Please give your database password
# Example: db_pass=pass_word_with_no_blanks_in_it
# Example: db_pass="this password has blanks in it"
db_pass=
###############################################
### MANDATORY - let's encrypt #################
#
# Hubilla requires encrypted communication via secure HTTP (HTTPS).
# This script automates installation of an SSL certificate from
# Let's Encrypt (https://letsencrypt.org)
#
# Please give the domain name of your hub
#
# Example: my.cooldomain.org
# Example: cooldomain.org
#
# Email is optional
#
#
le_domain=
le_email=
###############################################
### OPTIONAL - selfHOST - dynamic IP address ##
#
# 1. Register a domain at selfhost.de
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 08.01.2016
# 2. Get your configuration for dynamic IP update
# - Log in at selfhost.de
# - go to "DynDNS Accounte"
# - klick "Details" of your (freshly) registered domain
# - You will find the configuration there
# - Benutzername (user name) > use this for "selfhost_user="
# - Passwort (pass word) > use this for "selfhost_pass="
#
#
selfhost_user=
selfhost_pass=
###############################################
### OPTIONAL - FreeDNS - dynamic IP address ###
#
# Please give the alpha-numeric-key of freedns
#
# Get a free subdomain from freedns and use it for your dynamic ip address
# Documentation under http://www.techjawab.com/2013/06/setup-dynamic-dns-dyndns-for-free-on.html
#
# - Register for a Free domain at http://freedns.afraid.org/signup/
# - WATCH THIS: Make sure you choose a domain with as less subdomains as
# possible. Why? Let's encrpyt issues a limited count of certificates each
# day. Possible other users of this domain will try to issue a certificate
# at the same day.
# - Logon to FreeDNS (where you just registered)
# - Goto http://freedns.afraid.org/dynamic/
# - Right click on "Direct Link" and copy the URL and paste it somewhere.
# - You should notice a large and unique alpha-numeric key in the URL
#
# http://freedns.afraid.org/dynamic/update.php?alpha-numeric-key
#
# Provided your url from freedns is
#
# http://freedns.afraid.org/dynamic/update.php?U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
#
# Then you have to provide
#
# freedns_key=U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
#
#
#freedns_key=
###############################################
### OPTIONAL - Backup to external device ######
#
# The script can use an external device for the daily backup.
# The file system of the device (USB stick for example) must be compatible
# with encrypted LUKS + ext4
#
# You should test to mount the device befor you run the script
# (hubzilla-setup.sh).
# How to find your (pluged-in) devices?
#
# fdisk -l
#
# Provided your device was listed as is /dev/sdb1. You could check with:
#
# blkid | grep /dev/sdb1
#
# Try to decrypt
# (You might install cryptsetup befor using apt-get install.
#
# apt-get install cryptsetup
# cryptsetup luksOpen /dev/sdb1 cryptobackup
#
# Try to mount
# You might create the directory /media/hubzilla_backup it it does not exist
# using mkdir.
#
# mkdir /media/hubzilla_backup
# mount /dev/mapper/cryptobackup /media/hubzilla_backup
#
# Unmounting device goes like this
#
# umount /media/hubzilla_backup
# cryptsetup luksClose cryptobackup
#
# To check if still mounted
#
# lsof /media/hubzilla_backup
#
# If you leave the following parameters
# - "backup_device_name" and
# - "backup_device_pass"
# empty the script will create daily backups on the internal disk (which could
# save you as well).
#
# Example: backup_device_name=/dev/sdc1
#
backup_device_name=
backup_device_pass=
###############################################
### OPTIONAL - Owncloud - deprecated ##########
#
# To install owncloud: owncloud=y
# Leave empty if you don't want to install owncloud
#
#owncloud=
###############################################
### OPTIONAL - do not mess with things below ##
# (...if you are not certain)
#
# Usually you are done here
# Everything below is OPTIONAL
#
###############################################
#
# Database for hubzilla
hubzilla_db_name=hubzilla
hubzilla_db_user=hubzilla
hubzilla_db_pass=$db_pass
#
#
# Password for package mysql-server
# Example: mysqlpass=aberhallo
# Example: mysqlpass="aber hallo has blanks in it"
#
mysqlpass=$db_pass
# Password for package phpmyadmin
# Example: phpmyadminpass=aberhallo
# Example: phpmyadminpass="aber hallo has blanks in it"
phpmyadminpass=$db_pass
# TODO Prepare hubzilla for programmers
# - install eclipse and plugins
# - install xdebug to debug the php with eclipse
# - weaken permissions on /var/www/html
# - manual steps after this script
# * in eclipse: install plugins for php git hub
# * in eclipse: configure firefox (chrome,...) as browser to run with the php debuger
# * in eclipse: switch php debugger from zend to xdebug
# * in eclipse: add local hubzilla github repository
#
# Which user will use eclipse?
# Leave this empty if you do not want to prepare hubzilla for debugging
#
#developer_name=

949
.homeinstall/hubzilla-setup.sh Executable file
View File

@@ -0,0 +1,949 @@
#!/bin/bash
#
# How to use
# ----------
#
# This file automates the installation of hubzilla under Debian Linux
#
# 1) Copy the file "hubzilla-config.txt.template" to "hubzilla-config.txt"
# Follow the instuctions there
#
# 2) Switch to user "root" by typing "su -"
#
# 3) Run with "./hubzilla-setup.sh"
# If this fails check if you can execute the script.
# - To make it executable type "chmod +x hubzilla-setup.sh"
# - or run "bash hubzilla-setup.sh"
#
#
# What does this script do basically?
# -----------------------------------
#
# This file automates the installation of hubzilla under Debian Linux
# - install
# * apache webserer,
# * php,
# * mysql - the database for hubzilla,
# * phpmyadmin,
# * git to download and update hubzilla itself
# - download hubzilla core and addons
# - configure cron
# * "poller.php" for regular background prozesses of hubzilla
# * to_do "apt-get update" and "apt-get dist-upgrade" to keep linux
# up-to-date
# * to_do backup hubzillas database and files (rsnapshot)
# - configure dynamic ip with cron
# - to_do letsencrypt
# - to_do redirection to https
#
#
# Discussion
# ----------
#
# Security - password is the same for mysql-server, phpmyadmin and hubzilla db
# - The script runs into installation errors for phpmyadmin if it uses
# different passwords. For the sake of simplicity one singel password.
#
# Security - suhosin for PHP
# - The script does not install suhosin.
# - Is the security package suhosin usefull or not usefull?
#
# Hubzilla - email verification
# - The script switches off email verification off in all htconfig.tpl.
# Example: /var/www/html/view/en/htconfig.tpl
# - Is this a silly idea or not?
#
#
# Remove Hubzilla (for a fresh start using the script)
# ----------------------------------------------------
#
# You could use /var/www/hubzilla-remove.sh
# that is created by hubzilla-setup.sh.
#
# The script will remove (almost everything) what was installed by the script.
# After the removal you could run the script again to have a fresh install
# of all applications including hubzilla and its database.
#
# How to restore from backup
# --------------------------
#
# Daily backup
# - - - - - -
#
# The installation
# - writes a script /var/www/hubzilla-daily.sh
# - creates a daily cron that runs the hubzilla-daily.sh
#
# hubzilla-daily.sh makes a (daily) backup of all relevant files
# - /var/lib/mysql/ > hubzilla database
# - /var/www/html/ > hubzilla from github
# - /var/www/letsencrypt/ > certificates
#
# hubzilla-daily.sh writes the backup
# - either to an external disk compatible to LUKS+ext4 (see hubzilla-config.txt)
# - or to /var/cache/rsnapshot in case the external disk is not plugged in
#
# Restore backup
# - - - - - - -
#
# This was not tested yet.
# Bacically you can copy the files from the backup to the server.
#
# Credits
# -------
#
# The script is based on Thomas Willinghams script "debian-setup.sh"
# which he used to install the red#matrix.
#
# The script uses another script from https://github.com/lukas2511/letsencrypt.sh
#
# The documentation for bash is here
# https://www.gnu.org/software/bash/manual/bash.html
#
function check_sanity {
# Do some sanity checking.
print_info "Sanity check..."
if [ $(/usr/bin/id -u) != "0" ]
then
die 'Must be run by root user'
fi
if [ -f /etc/lsb-release ]
then
die "Distribution is not supported"
fi
if [ ! -f /etc/debian_version ]
then
die "Ubuntu is not supported"
fi
}
function check_config {
print_info "config check..."
# Check for required parameters
if [ -z "$db_pass" ]
then
die "db_pass not set in $configfile"
fi
if [ -z "$le_domain" ]
then
die "le_domain not set in $configfile"
fi
# backup is important and should be checked
if [ -n "$backup_device_name" ]
then
device_mounted=0
if fdisk -l | grep -i "$backup_device_name.*linux"
then
print_info "ok - filesystem of external device is linux"
if [ -n "$backup_device_pass" ]
then
echo "$backup_device_pass" | cryptsetup luksOpen $backup_device_name cryptobackup
if [ ! -d /media/hubzilla_backup ]
then
mkdir /media/hubzilla_backup
fi
if mount /dev/mapper/cryptobackup /media/hubzilla_backup
then
device_mounted=1
print_info "ok - could encrypt and mount external backup device"
umount /media/hubzilla_backup
else
print_warn "backup to external device will fail because encryption failed"
fi
cryptsetup luksClose cryptobackup
else
if mount $backup_device_name /media/hubzilla_backup
then
device_mounted=1
print_info "ok - could mount external backup device"
umount /media/hubzilla_backup
else
print_warn "backup to external device will fail because mount failed"
fi
fi
else
print_warn "backup to external device will fail because filesystem is either not linux or 'backup_device_name' is not correct in $configfile"
fi
if [ $device_mounted == 0 ]
then
die "backup device not ready"
fi
fi
}
function die {
echo "ERROR: $1" > /dev/null 1>&2
exit 1
}
function update_upgrade {
print_info "updated and upgrade..."
# Run through the apt-get update/upgrade first. This should be done before
# we try to install any package
apt-get -q -y update && apt-get -q -y dist-upgrade
print_info "updated and upgraded linux"
}
function check_install {
if [ -z "`which "$1" 2>/dev/null`" ]
then
# export DEBIAN_FRONTEND=noninteractive ... answers from the package
# configuration database
# - q ... without progress information
# - y ... answer interactive questions with "yes"
# DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -q -y install $2
DEBIAN_FRONTEND=noninteractive apt-get -q -y install $2
print_info "installed $2 installed for $1"
else
print_warn "$2 already installed"
fi
}
function nocheck_install {
# export DEBIAN_FRONTEND=noninteractive ... answers from the package configuration database
# - q ... without progress information
# - y ... answer interactive questions with "yes"
# DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -q -y install $2
# DEBIAN_FRONTEND=noninteractive apt-get --install-suggests -q -y install $1
DEBIAN_FRONTEND=noninteractive apt-get -q -y install $1
print_info "installed $1"
}
function print_info {
echo -n -e '\e[1;34m'
echo -n $1
echo -e '\e[0m'
}
function print_warn {
echo -n -e '\e[1;31m'
echo -n $1
echo -e '\e[0m'
}
function stop_hubzilla {
if [ -d /etc/apache2 ]
then
print_info "stopping apache webserver..."
service apache2 stop
fi
if [ -f /etc/init.d/mysql ]
then
print_info "stopping mysql db..."
/etc/init.d/mysql stop
fi
}
function install_apache {
print_info "installing apache..."
nocheck_install "apache2 apache2-utils"
}
function install_curl {
print_info "installing curl..."
nocheck_install "curl"
}
function install_sendmail {
print_info "installing sendmail..."
nocheck_install "sendmail sendmail-bin"
}
function install_php {
# openssl and mbstring are included in libapache2-mod-php5
# to_to: php5-suhosin
print_info "installing php..."
nocheck_install "libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd"
php5enmod mcrypt
}
function install_mysql {
# http://www.microhowto.info/howto/perform_an_unattended_installation_of_a_debian_package.html
#
# To determine the required package name, key and type you can perform
# a trial installation then search the configuration database.
#
# debconf-get-selections | grep mysql-server
#
# The command debconf-get-selections is provided by the package
# debconf-utils, which you may need to install.
#
# apt-get install debconf-utils
#
# If you want to supply an answer to a configuration question but do not
# want to be prompted for it then this can be arranged by preseeding the
# DebConf database with the required information.
#
# echo mysql-server-5.5 mysql-server/root_password password xyzzy | debconf-set-selections
# echo mysql-server-5.5 mysql-server/root_password_again password xyzzy | debconf-set-selections
#
print_info "installing mysql..."
if [ -z "$mysqlpass" ]
then
die "mysqlpass not set in $configfile"
fi
echo mysql-server-5.5 mysql-server/root_password password $mysqlpass | debconf-set-selections
echo mysql-server-5.5 mysql-server/root_password_again password $mysqlpass | debconf-set-selections
nocheck_install "php5-mysql mysql-server mysql-client"
php5enmod mcrypt
}
function install_phpmyadmin {
print_info "installing phpmyadmin..."
if [ -z "$phpmyadminpass" ]
then
die "phpmyadminpass not set in $configfile"
fi
echo phpmyadmin phpmyadmin/setup-password password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/mysql/app-pass password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/app-password-confirm password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/mysql/admin-pass password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/password-confirm password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/reconfigure-webserver multiselect apache2 | debconf-set-selections
nocheck_install "phpmyadmin"
# It seems to be not neccessary to check rewrite.load because it comes
# with the installation. To be sure you could check this manually by:
#
# nano /etc/apache2/mods-available/rewrite.load
#
# You should find the content:
#
# LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so
a2enmod rewrite
if [ ! -f /etc/apache2/apache2.conf ]
then
die "could not find file /etc/apache2/apache2.conf"
fi
sed -i \
"s/AllowOverride None/AllowOverride all/" \
/etc/apache2/apache2.conf
if [ -z "`grep 'Include /etc/phpmyadmin/apache.conf' /etc/apache2/apache2.conf`" ]
then
echo "Include /etc/phpmyadmin/apache.conf" >> /etc/apache2/apache2.conf
fi
service apache2 restart
}
function create_hubzilla_db {
print_info "creating hubzilla database..."
if [ -z "$hubzilla_db_name" ]
then
die "hubzilla_db_name not set in $configfile"
fi
if [ -z "$hubzilla_db_user" ]
then
die "hubzilla_db_user not set in $configfile"
fi
if [ -z "$hubzilla_db_pass" ]
then
die "hubzilla_db_pass not set in $configfile"
fi
Q1="CREATE DATABASE IF NOT EXISTS $hubzilla_db_name;"
Q2="GRANT USAGE ON *.* TO $hubzilla_db_user@localhost IDENTIFIED BY '$hubzilla_db_pass';"
Q3="GRANT ALL PRIVILEGES ON $hubzilla_db_name.* to $hubzilla_db_user@localhost identified by '$hubzilla_db_pass';"
Q4="FLUSH PRIVILEGES;"
SQL="${Q1}${Q2}${Q3}${Q4}"
mysql -uroot -p$phpmyadminpass -e "$SQL"
}
function run_freedns {
print_info "run freedns (dynamic IP)..."
if [ -z "$freedns_key" ]
then
print_info "freedns was not started because 'freedns_key' is empty in $configfile"
else
if [ -n "$selfhost_user" ]
then
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
fi
wget --no-check-certificate -O - https://freedns.afraid.org/dynamic/update.php?$freedns_key
fi
}
function install_run_selfhost {
print_info "install and start selfhost (dynamic IP)..."
if [ -z "$selfhost_user" ]
then
print_info "selfHOST was not started because 'selfhost_user' is empty in $configfile"
else
if [ -n "$freedns_key" ]
then
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
fi
if [ -z "$selfhost_pass" ]
then
die "selfHOST was not started because 'selfhost_pass' is empty in $configfile"
fi
if [ ! -d $selfhostdir ]
then
mkdir $selfhostdir
fi
# the old way
# https://carol.selfhost.de/update?username=123456&password=supersafe
#
# the prefered way
wget --output-document=$selfhostdir/$selfhostscript http://jonaspasche.de/selfhost-updater
echo "router" > $selfhostdir/device
echo "$selfhost_user" > $selfhostdir/user
echo "$selfhost_pass" > $selfhostdir/pass
bash $selfhostdir/$selfhostscript update
fi
}
function ping_domain {
print_info "ping domain $domain..."
# Is the domain resolved? Try to ping 6 times à 10 seconds
COUNTER=0
for i in {1..6}
do
print_info "loop $i for ping -c 1 $domain ..."
if ping -c 4 -W 1 $le_domain
then
print_info "$le_domain resolved"
break
else
if [ $i -gt 5 ]
then
die "Failed to: ping -c 1 $domain not resolved"
fi
fi
sleep 10
done
sleep 5
}
function configure_cron_freedns {
print_info "configure cron for freedns..."
if [ -z "$freedns_key" ]
then
print_info "freedns is not configured because freedns_key is empty in $configfile"
else
# Use cron for dynamich ip update
# - at reboot
# - every 30 minutes
if [ -z "`grep 'freedns.afraid.org' /etc/crontab`" ]
then
echo "@reboot root https://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
echo "*/30 * * * * root wget --no-check-certificate -O - https://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
else
print_info "cron for freedns was configured already"
fi
fi
}
function configure_cron_selfhost {
print_info "configure cron for selfhost..."
if [ -z "$selfhost_user" ]
then
print_info "freedns is not configured because freedns_key is empty in $configfile"
else
# Use cron for dynamich ip update
# - at reboot
# - every 30 minutes
if [ -z "`grep 'selfhost-updater.sh' /etc/crontab`" ]
then
echo "@reboot root bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
echo "*/5 * * * * root /bin/bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
else
print_info "cron for selfhost was configured already"
fi
fi
}
function install_git {
print_info "installing git..."
nocheck_install "git"
}
function install_letsencrypt {
print_info "installing let's encrypt ..."
# check if user gave domain
if [ -z "$le_domain" ]
then
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
fi
# configure apache
apache_le_conf=/etc/apache2/sites-available/le-default.conf
if [ -f $apache_le_conf ]
then
print_info "$apache_le_conf exist already"
else
cat > $apache_le_conf <<END
# letsencrypt default Apache configuration
Alias /.well-known/acme-challenge /var/www/letsencrypt
<Directory /var/www/letsencrypt>
Options FollowSymLinks
Allow from all
</Directory>
END
a2ensite le-default.conf
service apache2 restart
fi
# download the shell script
if [ -d $le_dir ]
then
print_info "letsenrypt exists already (nothing downloaded > no certificate created and registered)"
return 0
fi
git clone https://github.com/lukas2511/letsencrypt.sh $le_dir
cd $le_dir
# create config file for letsencrypt.sh
echo "WELLKNOWN=$le_dir" > $le_dir/config.sh
if [ -n "$le_email" ]
then
echo "CONTACT_EMAIL=$le_email" >> $le_dir/config.sh
fi
# create domain file for letsencrypt.sh
# WATCH THIS:
# - It did not work wit "sub.domain.org www.sub.domain.org".
# - So just use "sub.domain.org" only!
echo "$le_domain" > $le_dir/domains.txt
# test apache config for letsencrpyt
url_http=http://$le_domain/.well-known/acme-challenge/domains.txt
wget_output=$(wget -nv --spider --max-redirect 0 $url_http)
if [ $? -ne 0 ]
then
die "Failed to load $url_http"
fi
# run letsencrypt.sh
#
./letsencrypt.sh --cron
}
function configure_apache_for_https {
print_info "configuring apache to use httpS ..."
# letsencrypt.sh
#
# "${BASEDIR}/certs/${domain}/privkey.pem"
# "${BASEDIR}/certs/${domain}/cert.pem"
# "${BASEDIR}/certs/${domain}/fullchain.pem"
#
SSLCertificateFile=${le_dir}/certs/${le_domain}/cert.pem
SSLCertificateKeyFile=${le_dir}/certs/${le_domain}/privkey.pem
SSLCertificateChainFile=${le_dir}/certs/${le_domain}/fullchain.pem
if [ ! -f $SSLCertificateFile ]
then
print_warn "Failed to configure apache for httpS: Missing certificate file $SSLCertificateFile"
return 0
fi
# make sure that the ssl mode is enabled
print_info "...configuring apache to use httpS - a2enmod ssl ..."
a2enmod ssl
# modify apach' ssl conf file
if grep -i "ServerName" $sslconf
then
print_info "seems that apache was already configered to use httpS with $sslconf"
else
sed -i "s/ServerAdmin.*$/ServerAdmin webmaster@localhost\\n ServerName ${le_domain}/" $sslconf
fi
sed -i s#/etc/ssl/certs/ssl-cert-snakeoil.pem#$SSLCertificateFile# $sslconf
sed -i s#/etc/ssl/private/ssl-cert-snakeoil.key#$SSLCertificateKeyFile# $sslconf
sed -i s#/etc/apache2/ssl.crt/server-ca.crt#$SSLCertificateChainFile# $sslconf
sed -i s/#SSLCertificateChainFile/SSLCertificateChainFile/ $sslconf
# apply changes
a2ensite default-ssl.conf
service apache2 restart
}
function check_https {
print_info "checking httpS > testing ..."
url_https=https://$le_domain
wget_output=$(wget -nv --spider --max-redirect 0 $url_https)
if [ $? -ne 0 ]
then
print_warn "check not ok"
else
print_info "check ok"
fi
}
function install_hubzilla {
print_info "installing hubzilla..."
# rm -R /var/www/html/ # for "stand alone" usage
cd /var/www/
# git clone https://github.com/redmatrix/hubzilla html # for "stand alone" usage
cd html/
git clone https://github.com/redmatrix/hubzilla-addons addon
mkdir -p "store/[data]/smarty3"
chmod -R 777 store
touch .htconfig.php
chmod ou+w .htconfig.php
install_hubzilla_plugins
cd /var/www/
chown -R www-data:www-data html
chown root:www-data /var/www/html/
chown root:www-data /var/www/html/.htaccess
chmod 0644 /var/www/html/.htaccess
# try to switch off email registration
sed -i "s/verify_email.*1/verify_email'] = 0/" /var/www/html/view/*/ht*
if [ -n "`grep -r 'verify_email.*1' /var/www/html/view/`" ]
then
print_warn "Hubzillas registration prozess might have email verification switched on."
fi
print_info "installed hubzilla"
}
function install_hubzilla_plugins {
print_info "installing hubzilla plugins..."
cd /var/www/html
plugin_install=.homeinstall/plugin_install.txt
theme_install=.homeinstall/theme_install.txt
# overwrite script to update the plugin and themes
rm -f $plugins_update
echo "cd /var/www/html" >> $plugins_update
###################
# write plugin file
if [ ! -f "$plugin_install" ]
then
echo "# To install a plugin" >> $plugin_install
echo "# 1. add the plugin in a new line and run" >> $plugin_install
echo "# 2. run" >> $plugin_install
echo "# cd /var/www/html/.homeinstall" >> $plugin_install
echo "# ./hubzilla-setup.sh" >> $plugin_install
echo "https://gitlab.com/zot/ownmapp.git ownMapp" >> $plugin_install
echo "https://gitlab.com/zot/hubzilla-chess.git chess" >> $plugin_install
fi
# install plugins
while read -r line; do
[[ "$line" =~ ^#.*$ ]] && continue
p_url=$(echo $line | awk -F' ' '{print $1}')
p_name=$(echo $line | awk -F' ' '{print $2}')
# basic check of format
if [ ${#p_url} -ge 1 ] && [ ${#p_name} -ge 1 ]
then
# install addon
util/add_addon_repo $line
util/update_addon_repo $p_name # not sure if this line is neccessary
echo "util/update_addon_repo $p_name" >> $plugins_update
else
print_info "skipping installation of a plugin from file $plugin_install - something wrong with format in line: $line"
fi
done < "$plugin_install"
###################
# write theme file
if [ ! -f "$theme_install" ]
then
echo "# To install a theme" >> $theme_install
echo "# 1. add the theme in a new line and run" >> $theme_install
echo "# 2. run" >> $theme_install
echo "# cd /var/www/html/.homeinstall" >> $theme_install
echo "# ./hubzilla-setup.sh" >> $theme_install
echo "https://github.com/DeadSuperHero/hubzilla-themes.git DeadSuperHeroThemes" >> $theme_install
fi
# install plugins
while read -r line; do
[[ "$line" =~ ^#.*$ ]] && continue
p_url=$(echo $line | awk -F' ' '{print $1}')
p_name=$(echo $line | awk -F' ' '{print $2}')
# basic check of format
if [ ${#p_url} -ge 1 ] && [ ${#p_name} -ge 1 ]
then
# install addon
util/add_theme_repo $line
util/update_theme_repo $p_name # not sure if this line is neccessary
echo "util/update_theme_repo $p_name" >> $plugins_update
else
print_info "skipping installation of a theme from file $theme_install - something wrong with format in line: $line"
fi
done < "$theme_install"
print_info "installed hubzilla plugins and themes"
}
function rewrite_to_https {
print_info "configuring apache to redirect http to httpS ..."
htaccessfile=/var/www/html/.htaccess
if grep -i "https" $htaccessfile
then
print_info "...configuring apache to redirect http to httpS was already done in $htaccessfile"
else
sed -i "s#QSA]#QSA]\\n RewriteCond %{SERVER_PORT} !^443$\\n RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]#" $htaccessfile
fi
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)
# of rsnapshot for hubzilla
function install_rsnapshot {
print_info "installing rsnapshot..."
nocheck_install "rsnapshot"
# internal disk
cp -f /etc/rsnapshot.conf $snapshotconfig
sed -i "/hourly/s/retain/#retain/" $snapshotconfig
sed -i "/monthly/s/#retain/retain/" $snapshotconfig
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig
sed -i "s/^backup/#backup/" $snapshotconfig
if [ -z "`grep 'letsencrypt' $snapshotconfig`" ]
then
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig
echo "backup /var/www/html/ localhost/" >> $snapshotconfig
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig
fi
# external disk
if [ -n "$backup_device_name" ] && [ -n "$backup_device_pass" ]
then
cp -f /etc/rsnapshot.conf $snapshotconfig_external_device
sed -i "s#snapshot_root.*#snapshot_root $backup_mount_point#" $snapshotconfig_external_device
sed -i "/hourly/s/retain/#retain/" $snapshotconfig_external_device
sed -i "/monthly/s/#retain/retain/" $snapshotconfig_external_device
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig_external_device
sed -i "s/^backup/#backup/" $snapshotconfig_external_device
if [ -z "`grep 'letsencrypt' $snapshotconfig_external_device`" ]
then
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig_external_device
echo "backup /var/www/html/ localhost/" >> $snapshotconfig_external_device
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig_external_device
fi
else
print_info "No backup configuration (rsnapshot) for external device configured. Reason: backup_device_name and/or backup_device_pass not given in $configfile"
fi
}
function install_cryptosetup {
print_info "installing cryptsetup..."
nocheck_install "cryptsetup"
}
function configure_cron_daily {
print_info "configuring cron..."
# every 10 min for poller.php
if [ -z "`grep 'poller.php' /etc/crontab`" ]
then
echo "*/10 * * * * www-data cd /var/www/html; php include/poller.php >> /dev/null 2>&1" >> /etc/crontab
fi
# Run external script daily at 05:30
# - stop apache and mysql-server
# - backup hubzilla
# - update hubzilla core and addon
# - update and upgrade linux
# - reboot
echo "#!/bin/sh" > /var/www/$hubzilladaily
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 "#" >> /var/www/$hubzilladaily
echo "# stop hubzilla" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - stoping apaache 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
echo "# backup" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - try to mount external device for backup...\"" >> /var/www/$hubzilladaily
echo "backup_device_name=$backup_device_name" >> /var/www/$hubzilladaily
echo "backup_device_pass=$backup_device_pass" >> /var/www/$hubzilladaily
echo "backup_mount_point=$backup_mount_point" >> /var/www/$hubzilladaily
echo "device_mounted=0" >> /var/www/$hubzilladaily
echo "if [ -n \"$backup_device_name\" ]" >> /var/www/$hubzilladaily
echo "then" >> /var/www/$hubzilladaily
echo " if blkid | grep $backup_device_name" >> /var/www/$hubzilladaily
echo " then" >> /var/www/$hubzilladaily
if [ -n "$backup_device_pass" ]
then
echo " echo \"decrypting backup device...\"" >> /var/www/$hubzilladaily
echo " echo "\"$backup_device_pass\"" | cryptsetup luksOpen $backup_device_name cryptobackup" >> /var/www/$hubzilladaily
fi
echo " if [ ! -d $backup_mount_point ]" >> /var/www/$hubzilladaily
echo " then" >> /var/www/$hubzilladaily
echo " mkdir $backup_mount_point" >> /var/www/$hubzilladaily
echo " fi" >> /var/www/$hubzilladaily
echo " echo \"mounting backup device...\"" >> /var/www/$hubzilladaily
if [ -n "$backup_device_pass" ]
then
echo " if mount /dev/mapper/cryptobackup $backup_mount_point" >> /var/www/$hubzilladaily
else
echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$hubzilladaily
fi
echo " then" >> /var/www/$hubzilladaily
echo " device_mounted=1" >> /var/www/$hubzilladaily
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig_external_device daily" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig_external_device weekly" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig_external_device monthly" >> /var/www/$hubzilladaily
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$hubzilladaily
echo " df -h" >> /var/www/$hubzilladaily
echo " echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
echo " du -h $backup_mount_point | grep mysql/hubzilla" >> /var/www/$hubzilladaily
echo " echo \"unmounting backup device...\"" >> /var/www/$hubzilladaily
echo " umount $backup_mount_point" >> /var/www/$hubzilladaily
echo " else" >> /var/www/$hubzilladaily
echo " echo \"failed to mount device $backup_device_name\"" >> /var/www/$hubzilladaily
echo " fi" >> /var/www/$hubzilladaily
if [ -n "$backup_device_pass" ]
then
echo " echo \"closing decrypted backup device...\"" >> /var/www/$hubzilladaily
echo " cryptsetup luksClose cryptobackup" >> /var/www/$hubzilladaily
fi
echo " fi" >> /var/www/$hubzilladaily
echo "fi" >> /var/www/$hubzilladaily
echo "if [ \$device_mounted == 0 ]" >> /var/www/$hubzilladaily
echo "then" >> /var/www/$hubzilladaily
echo " echo \"device could not be mounted $backup_device_name. Using internal disk for backup...\"" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig daily" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig weekly" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig monthly" >> /var/www/$hubzilladaily
echo "fi" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
echo "du -h /var/cache/rsnapshot/ | grep mysql/hubzilla" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "# update" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - updating letsencrypt.sh...\"" >> /var/www/$hubzilladaily
echo "git -C /var/www/letsencrypt/ pull" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - updating hubhilla core...\"" >> /var/www/$hubzilladaily
echo "git -C /var/www/html/ pull" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - updating hubhilla addons...\"" >> /var/www/$hubzilladaily
echo "git -C /var/www/html/addon/ pull" >> /var/www/$hubzilladaily
echo "bash /var/www/html/$plugins_update" >> /var/www/$hubzilladaily
echo "chown -R www-data:www-data /var/www/html/ # make all accessable for the webserver" >> /var/www/$hubzilladaily
echo "chown root:www-data /var/www/html/.htaccess" >> /var/www/$hubzilladaily
echo "chmod 0644 /var/www/html/.htaccess # www-data can read but not write it" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$hubzilladaily
echo "apt-get -q -y update && apt-get -q -y dist-upgrade # update linux and upgrade" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - Backup hubzilla and update linux finished. Rebooting...\"" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "reboot" >> /var/www/$hubzilladaily
if [ -z "`grep 'hubzilla-daily.sh' /etc/crontab`" ]
then
echo "30 05 * * * root /bin/bash /var/www/$hubzilladaily >> /var/www/html/hubzilla-daily.log 2>&1" >> /etc/crontab
echo "0 0 1 * * root rm /var/www/html/hubzilla-daily.log" >> /etc/crontab
fi
# This is active after either "reboot" or "/etc/init.d/cron reload"
print_info "configured cron for updates/upgrades"
}
function write_uninstall_script {
print_info "writing uninstall script..."
cat > /var/www/hubzilla-remove.sh <<END
#!/bin/sh
#
# This script removes Hubzilla.
# You might do this for a fresh start using the script.
# The script will remove (almost everything) what was installed by the script,
# all applications including hubzilla and its database.
#
# Backup the certificates of letsencrypt (you never know)
cp -a /var/www/letsencrypt/ ~/backup_le_certificats
#
# Removal
apt-get remove apache2 apache2-utils libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd php5-mysql mysql-server mysql-client phpmyadmin
apt-get purge apache2 apache2-utils libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd php5-mysql mysql-server mysql-client phpmyadmin
apt-get autoremove
apt-get clean
rm /etc/rsnapshot_hubzilla.conf
rm /etc/rsnapshot_hubzilla_external_device.conf
rm -R /etc/apache2/
rm -R /var/lib/mysql/
rm -R /var/www
rm -R /etc/selfhost/
# uncomment the next line if you want to remove the backups
# rm -R /var/cache/rsnapshot
nano /etc/crontab # remove entries there manually
END
chmod -x /var/www/hubzilla-remove.sh
}
########################################################################
# START OF PROGRAM
########################################################################
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
check_sanity
# Read config file edited by user
configfile=hubzilla-config.txt
source $configfile
selfhostdir=/etc/selfhost
selfhostscript=selfhost-updater.sh
hubzilladaily=hubzilla-daily.sh
plugins_update=.homeinstall/plugins_update.sh
snapshotconfig=/etc/rsnapshot_hubzilla.conf
snapshotconfig_external_device=/etc/rsnapshot_hubzilla_external_device.conf
backup_mount_point=/media/hubzilla_backup
le_dir=/var/www/letsencrypt
sslconf=/etc/apache2/sites-available/default-ssl.conf
#set -x # activate debugging from here
check_config
stop_hubzilla
update_upgrade
install_curl
install_sendmail
install_apache
install_php
install_mysql
install_phpmyadmin
create_hubzilla_db
run_freedns
install_run_selfhost
ping_domain
configure_cron_freedns
configure_cron_selfhost
install_git
install_letsencrypt
configure_apache_for_https
check_https
install_hubzilla
rewrite_to_https
# install_owncloud # deprecated
install_rsnapshot
configure_cron_daily
install_cryptosetup
write_uninstall_script
#set +x # stop debugging from here

View File

@@ -24,6 +24,9 @@ AddType audio/ogg .oga
# Also place auth information into REMOTE_USER for sites running # Also place auth information into REMOTE_USER for sites running
# in CGI mode. # in CGI mode.
RewriteCond %{REQUEST_URI} ^/\.well\-known/.*
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA] RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]

View File

@@ -179,8 +179,11 @@ echo "chmod done, permissions set to 777 on poller script."
# Hubzilla configuration - changes to default settings # Hubzilla configuration - changes to default settings
# to make Hubzilla on OpenShift a more pleasant experience # to make Hubzilla on OpenShift a more pleasant experience
echo "Changing default configuration to conserve space" echo "Changing default configuration to conserve space and autocreate a social private channel upon account registration"
cd ${OPENSHIFT_REPO_DIR} cd ${OPENSHIFT_REPO_DIR}
util/config system auto_channel_create
util/config system default_permissions_role social_private
util/config system workflow_channel_next channel
util/config system expire_delivery_reports 3 util/config system expire_delivery_reports 3
util/config system feed_contacts 0 util/config system feed_contacts 0
util/config system diaspora_enabled 0 util/config system diaspora_enabled 0
@@ -194,12 +197,22 @@ echo "Try to add or update Hubzilla addons"
cd ${OPENSHIFT_REPO_DIR} cd ${OPENSHIFT_REPO_DIR}
util/add_addon_repo https://github.com/redmatrix/hubzilla-addons.git HubzillaAddons util/add_addon_repo https://github.com/redmatrix/hubzilla-addons.git HubzillaAddons
# Hubzilla themes # Hubzilla themes - unofficial repo
echo "Try to add or update Hubzilla themes" echo "Try to add or update Hubzilla themes - unofficial repo"
cd ${OPENSHIFT_REPO_DIR} cd ${OPENSHIFT_REPO_DIR}
util/add_theme_repo https://github.com/DeadSuperHero/redmatrix-themes.git DeadSuperHeroThemes util/add_theme_repo https://github.com/DeadSuperHero/hubzilla-themes.git DeadSuperHeroThemes insecure
# Hubzilla ownMapp # Hubzilla ownMapp - unofficial repo
echo "Try to add or update Hubzilla ownMapp" echo "Try to add or update Hubzilla ownMapp - unofficial repo"
cd ${OPENSHIFT_REPO_DIR} cd ${OPENSHIFT_REPO_DIR}
util/add_addon_repo https://gitlab.com/zot/ownmapp.git ownMapp util/add_addon_repo https://gitlab.com/zot/ownmapp.git ownMapp insecure
# Hubzilla Chess - unofficial repo
echo "Try to add or update Hubzilla chess - unofficial repo"
cd ${OPENSHIFT_REPO_DIR}
util/add_addon_repo https://gitlab.com/zot/hubzilla-chess.git Chess insecure
# Hubzilla Hubsites - unofficial repo
echo "Try to add or update Hubzilla Hubsites - unofficial repo"
cd ${OPENSHIFT_REPO_DIR}
util/add_addon_repo https://gitlab.com/zot/hubsites.git Hubsites insecure

217
CHANGELOG Normal file
View File

@@ -0,0 +1,217 @@
Hubzilla 1.6
Cleanup and standardise the interfaces to the "jot" editor
Router re-written to support calling class object methods as controllers
All existing modules (160+) re-written as object classes
Plugin hook interface adapted to call static class methods
Context help improved dramatically with content for the most accessed pages.
Reverted a compatibility change to support GNU-social events. We copied their feed format and their feed format is wrong (XML namespace collisions).
Provide a querystring attribute to CSS/JS resources to avoid caching issues when our code changes (which is often).
Fix javascript detection and allow either positive or negative detection.
Refactor the plugin hook registration procedure, provide 'unregister all' ability.
Fix RSD (Real Simple Discovery) which has been broken for some time.
Update smarty library to 3.1.29
Update jquery.textcomplete to 1.3.4
Update font-awesome to 4.6.1
Update SabreDAV to 3.0 (PHP version requirements prevent us from pushing it further at this time)
Help text added to cmdline utilities config and pconfig
Reworking of the database logging facility to avoid the rare but troublesome recursion when the log facility needed to query the DB internally to obtain config parameters.
Implement singleton delivery (emulate nomadic identity to singleton networks and services)
Fix empty album name in photo activities when photo is stored in top level folder.
Allow engineering units to be used in service class data size restrictions (400M, 1G, etc.)
Lots of work on bbcode auto-completion
Admin interface provided to manage external resource repositories
Oembed security reworked. Now all sources are filtered by default unless blocked.
Remove the date-string version and use only STD_VERSION
Add categories and categorisation filtering and the ability to edit all apps (including system apps) for a given channel
Ensure the ability to translate names of all system apps (except those provided in addons)
Provide ability to add categories to content from channel sources
Lots of work on the presentation of the ACL widget to enhance usability and intuitiveness
Allow somebody to follow a channel from a pasted redress containing a Unicode lookalike of the @ sign.
Add conditional syntax to Comanche (if/then/else)
Convert Comanche to an object class
Removed IE6 compatibility code
Explicitly close DB on shutdown/exit instead of allowing it to close naturally
Allowed delayed publish of webpages
Show current repository versions of master and dev on admin page and warn if your installation has fallen behind master
Provide some extra security checks to import data and files to prevent mischief
Block CalDAV/CardDAV namespace reserved words from being used as a channel nickname/redress since Sabre is somewhat inflexible in this regard
Plugins:
Diaspora
markdown translator work needed to eradicate the Diaspora Comment Virus.
upgrade all inbound paths with the most recent protocol changes (several of these)
convert 'diaspora_meta' (Diaspora Comment Virus) to iconfig and eradicate from sites with Diaspora disabled
implement social relay and allow following tags
upgrade statistics.json to NodeInfo. Currently hubzilla sites are tagged as 'redmatrix' because the NodeInfo schema lacks extensibility and project names are used to designate protocol compatibility rather than protocol names.
Std-embeds
New addon to allow a handful of corporate providers to run unfiltered embed code (youtube, vimeo, soundcloud)
Various:
upgrade font-awesome icons and adapt a few addons to Objects and the new hook interface and new controller interface
Hubzilla 1.4
[This list may appear brief, but encompasses a huge amount of re-writing and re-factoring
of the internal code structure to gain long-term performance and stability and provide a standard
interface to alternate protocol federation plugins which were made possible by the UNO configuration.
UNO is a configuration of hubzilla introduced in 1.3 with reduced complexity and which provides
improved protocol federation potential to other networks by virtue of removing nomadic identity
(which is not possible to model or work around using other network protocols).]
Implement channel move operation for UNO configuration
Remove bookmark references in UNO (which has no bookmarks by default)
UI cleanup profiles/chat/manage
Refactor webfinger probes and salmon backend for GNU-social federation
SECURITY: DAV authentication exploit
Context help added
More help pages
Provide 'posts only' feed
Refactor App to remove globals
Refactor Session to remove globals
provide a fullscreen mode for selected modules and functions
Regression: some addon routes broken
fix "remember me"
Autocomplete tool extended to bbcode/comanche
Clone sync of file/photo updates
system rename (e.g. http to https or DNS name change) missing some connection photos
calendar module not blocked to public whhen block_public enabled
Use timeago.js in reshare content so that timestamps will be correct on federated reshares
Rework detection of JavaScript to avoid reload penalty under normal operation
Changed primary directory server to a hubzilla server
Plugins:
Diaspora - switch to alternate XML parser to avoid storing compound objects
GNU-Social - Huge amounts of work, federation somewhat working now, several issues remain
Friendica - Initial federation work (not yet published)
Hubzilla 1.3
Admin Security configuration page created which consolidates several previously hidden settings:
Communication white/black lists
Channel white/black lists
OEmbed white/black lists
Admin Profile Fields page created which manages the availability and order of standard profile fields and allows new fields to be created/managed
"Poke" module reworked - page UI updated and "poke basic" setting introduced which limits the available poke "verbs".
"Mood" module UI reworked
"profile_photo" module UI reworked
"cover_photo" module UI reworked
"new_channel" module UI reworked
"register" module UI reworked
"pubsites" module UI reworked
item-meta ("iconfig") created which implements arbitrary storage for item metadata for plugins
abook-meta ("abconfig") created which implements arbitrary storage for connection metadata for plugins
"Strict transport security header" made optional as it conflicts with some existing Apache/nginx configurations
"Hubzilla UNO" (Hubzilla with radically simplified and locked site settings) implemented as an install configuration.
.well-known directory conflict worked out to support LetsEncrypt cert ownership checks without disrupting webfinger and other internal uses of .well-known
Lots of work on 'zcards' which are self-contained HTML representations of a channel including cover photos, profile photos, and some text information
Long standing bug uncovered which failed to properly restrict the lower time limit for public feed requests
A number of fixes to "readmore" to fix page jumping
Bugfix: persons other than the channel owner who have permission to upload photos to a channel could not do so if the js_upload plugin/addon was enabled
Siteinfo incorrectly identifying secondary directory servers
Allow admin to set and lock features when UNO is configured
Atom feeds: alter how events are formatted to be compatible with GNU-social
Allow guest/visitor access to view personal calendar
Moved several more classes to "composer format" and provided an autoloader.
Bugfix: require existing password to change password
Bugfix: allow relative_date() to be translated to Polish which has more than two plural forms.
Plugin API: add "requires" keyword to module header to indicate dependent addons
ActivityStreams improvements and cleanup: photo and file activities
UI cleanup for editing profile when multiple profiles enabled
Removed the "markdown" feature as there are numerous issues and no maintainer.
Provide "footer" bbcode to ease theming of post footer content
Bugfix: install issues caused by composer code refactor and typo in postgres load file
Plugins:
keepout - "block public on steroids"
pubsubhubbub - provides PuSH support to Atom feeds, required for GNU-social federation
GNUsocial protocol - under development
Diaspora protocol - some work to ease migration to the new signing format
Diaspost - disabled; numerous issues and no maintainer
smileybutton - theme work and fixed compatibility with other jot-tools plugins
Hubzilla 1.2
Provide extra HTTP security headers (several of them).
Allow a site to disable delivery reports if disk space is limited
Regression: Wrong theme when viewing single post as non-member
Some Diaspora profile photos use relative URLs - force absolute
Add locked features to siteinfo report to aid remote debugging
Provide version compatibility checking to plugins (minversion, maxversion, and minphpversion)
Account config storage
Provide optional integrated registration and channel create form
cli utility for managing addons
issue with sharing photo "items"
cover photo manager: upload, crop, and store
cover photo widget created
rework the connections list page and provide a few management features there
fixed issue with Comanche layout definitions loaded by plugins
provide ability to separate delivery functions from item_store() and item_store_update() - some forum messages were being redelivered when cloned.
call build_sync_packet() on pdledit changes
Abstract the project name and version so these can be customised or removed
Allow hiding the ratings links on a per-site basis
db_type not present in international setup templates - was unable to choose postgres.
item_photo_menu logically divided into a) actions on the post, b) actions related to the author
bug: default channel not reset to 0 when last channel removed
create widget containing only the contact block
regression: public forums granted send stream permissions to connections
workaround Firefox's refusal to honour disabling autocomplete of passwords
regression: photo's uploaded to a channel by a guest (with file write permissions) not saved correctly.
provide mechanisms for custom .well-known handlers (needed for LetsEncrypt ownership verification)
proc_run modified to use exec() instead of proc_open() - causing issues on some PHP installations
remote delegation failure under a specific set of circumstances which we were finally able to duplicate
Delegation section of Channel Manager was missing names and contained useless notification icons.
Change "expire" channel setting to show system limit if there is one.
Regression: provide a one-click ignore of pending connection
Config to control directory keyword generation on client and server.
"Collections" renamed to "Privacy Groups", documentation improved
widget_item - allow use of page title instead of message id
Add site black/white list checking to all .well-known services
reduce incidents of screen jumping when "showmore" is activated
add oembed provider for photos
Addons:
CSS theming of pageheader plugin
xmpp addon ported from Friendica
Diaspora private mail issues after the third reply
Occasional issue with Diaspora connection requests
Add notification email to Diaspora PMs
Allow anonymising platform and version for statistics
msgfooter addon created
removed embedly plugin
sync clones after superblock addition
"keepout" plugin created
Hubzilla 1.1
Rewrote and simplified the Queue manager and delivery system
Rewrote and simplified the outer layers of the Zot protocol
Use a standard version numbering scheme in addition to the snapshot tags
Provide a channel blacklist for blocking channels with abusive or illegal content at the hub level
Make the black/white lists pluggable
Update template library
Support for letsencrypt certs in various places
Cleanup of login and register pages
Better error responses for permission denied on channel file repositories
Disabled the public stream by default for new installs (can be enabled if desired)
Cleanup of API authentication and rework the old OAuth1 stuff
Add API "status with media" support compatible with Twitter and conflicting method for GNU-social
Rework photo ActivityStreams objects to align better with ActivityStreams producers/consumers
Several minor API fixes to work better with AndStatus client
Invitation only site - experimental support added, needs more work
Fix delivery loop condition due to corrupted data which resulted in recursive upstream delivery
Provide more support for external (git) widget collections.
Extend the Queue API to 3rd-party network addons which have experienced downtime recently.
Regression: Inherited permissions were not explicitly set
Regression: "Xyz posted on your wall" notification sent when creating webpages at another channel
Regression: Custom permissions not pre-populated on channel creation with named role.
Provide "Public" string when a post can be made public, instead of "visible to default audience"
Allow hub admin to specify a default role type for the first channel created, reducing complexity
Ability for a hub admin to set feature defaults and lock them, reducing complexity
Change default expiration of delivery reports to 10 days to accomodate sites with reduced resources
Addons/Plugins:
Pageheader addon ported from Friendica
Hubwall (allow admin to send email to all accounts on this hub) created
GNU-social - queueing added
Diaspora - fixes for various failures to update profile photos, updates to queue API
Cross Domain Authenticated Chess (Andrew Manning's repository)
And... the normal "lots of bugs fixed, translations updated, and documentation improved"

View File

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

View File

@@ -3,24 +3,26 @@
Hubzilla - Community Server Hubzilla - Community Server
=========================== ===========================
Help us redefine the web - using integrated and united community websites. Connected and linked web communities.
-------------------------------------------------------------------------- -------------------------------------
[![Build Status](https://travis-ci.org/redmatrix/hubzilla.svg)](https://travis-ci.org/redmatrix/hubzilla) <p align="center" markdown="1">
<em><a href="https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt">Installing Hubzilla</a></em>
</p>
**What are Hubs?** **What are Hubz?**
Hubs are independent general-purpose websites that not only connect with their associated members and viewers, but also connect together to exchange personal communications and other information with each other. Hubz are independent general-purpose websites that not only connect with their associated members and viewers, but also connect together to exchange personal communications and other information with each other.
This allows hub members on any hub to securely and privately share anything; with anybody, on any hub - anywhere; or share stuff publicly with anybody on the internet if desired. This allows hub members on any hub to securely and privately share anything; with anybody, on any hub - anywhere; or share stuff publicly with anybody on the internet if desired.
**Hubzilla** is the server software which makes this possible. It is a sophisticated and unique combination of an open source content management system and a decentralised identity, communications, and permissions framework and protocol suite, built using common webserver technology (PHP/MySQL/Apache, although Mariadb or Postgres and Nginx could also be used - we're pretty easy). The end result is a level of systems integration, privacy control, and communications features that you wouldn't think are possible in either a content management system or a decentralised communications network. It also brings a new level of cooperation and privacy to the web and introduces the concept of personally owned "single sign-on" to web services across the entire internet. **Hubzilla** is the server software which makes this possible. It is a sophisticated and unique combination of an open source content management system and a decentralised identity, communications, and permissions framework and protocol suite, built using common webserver technology (PHP/MySQL/Apache and popular variants). The end result is a level of systems integration, privacy control, and communications features that you wouldn't think are possible in either a content management system or a decentralised communications network. It also brings a new level of cooperation and privacy to the web and introduces the concept of personally owned "single sign-on" to web services across the entire internet.
Hubzilla hubs are Hubzilla hubz are
* decentralised * decentralised
* inherently social * inherently social
* optionally inter-networked with other hubs * optionally inter-networked with other hubz
* privacy-enabled (privacy exclusions work across the entire internet to any registered identity on any compatible hubs) * privacy-enabled (privacy exclusions work across the entire internet to any registered identity on any compatible hubz)
Possible website applications include Possible website applications include
@@ -38,3 +40,8 @@ Possible website applications include
* dating websites * dating websites
* pretty much anything you can do on a traditional blog or community website, but that you could do better if you could easily connect it with other websites or privately share things across website boundaries. * pretty much anything you can do on a traditional blog or community website, but that you could do better if you could easily connect it with other websites or privately share things across website boundaries.
<p align="center" markdown="1">
<em><a href="https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt">Installing Hubzilla</a></em>
</p>
[![Build Status](https://travis-ci.org/redmatrix/hubzilla.svg)](https://travis-ci.org/redmatrix/hubzilla)

View File

@@ -0,0 +1,92 @@
<?php
namespace Zotlabs\Access;
class AccessList {
private $allow_cid;
private $allow_gid;
private $deny_cid;
private $deny_gid;
/* indicates if we are using the default constructor values or values that have been set explicitly. */
private $explicit;
function __construct($channel) {
if($channel) {
$this->allow_cid = $channel['channel_allow_cid'];
$this->allow_gid = $channel['channel_allow_gid'];
$this->deny_cid = $channel['channel_deny_cid'];
$this->deny_gid = $channel['channel_deny_gid'];
}
else {
$this->allow_cid = '';
$this->allow_gid = '';
$this->deny_cid = '';
$this->deny_gid = '';
}
$this->explicit = false;
}
function get_explicit() {
return $this->explicit;
}
/**
* Set AccessList from strings such as those in already
* existing stored data items
*/
function set($arr,$explicit = true) {
$this->allow_cid = $arr['allow_cid'];
$this->allow_gid = $arr['allow_gid'];
$this->deny_cid = $arr['deny_cid'];
$this->deny_gid = $arr['deny_gid'];
$this->explicit = $explicit;
}
/**
* return an array consisting of the current
* access list components where the elements
* are directly storable.
*/
function get() {
return array(
'allow_cid' => $this->allow_cid,
'allow_gid' => $this->allow_gid,
'deny_cid' => $this->deny_cid,
'deny_gid' => $this->deny_gid,
);
}
/**
* Set AccessList from arrays, such as those provided by
* acl_selector(). For convenience, a string (or non-array) input is
* assumed to be a comma-separated list and auto-converted into an array.
*/
function set_from_array($arr,$explicit = true) {
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
? $arr['contact_allow'] : explode(',',$arr['contact_allow']));
$this->allow_gid = perms2str((is_array($arr['group_allow']))
? $arr['group_allow'] : explode(',',$arr['group_allow']));
$this->deny_cid = perms2str((is_array($arr['contact_deny']))
? $arr['contact_deny'] : explode(',',$arr['contact_deny']));
$this->deny_gid = perms2str((is_array($arr['group_deny']))
? $arr['group_deny'] : explode(',',$arr['group_deny']));
$this->explicit = $explicit;
}
function is_private() {
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
}
}

107
Zotlabs/Extend/Hook.php Normal file
View File

@@ -0,0 +1,107 @@
<?php
namespace Zotlabs\Extend;
class Hook {
static public function register($hook,$file,$function,$version = 1,$priority = 0) {
if(is_array($function)) {
$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",
dbesc($hook),
dbesc($file),
dbesc($function),
intval($priority),
intval($version)
);
if($r)
return true;
// 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'",
dbesc($hook),
dbesc($file),
dbesc($function)
);
$r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`, `hook_version`) VALUES ( '%s', '%s', '%s', %d, %d )",
dbesc($hook),
dbesc($file),
dbesc($function),
intval($priority),
intval($version)
);
return $r;
}
static public function unregister($hook,$file,$function,$version = 1,$priority = 0) {
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",
dbesc($hook),
dbesc($file),
dbesc($function),
intval($priority),
intval($version)
);
return $r;
}
// unregister all hooks with this file component.
// Useful for addon upgrades where you want to clean out old interfaces.
static public function unregister_by_file($file) {
$r = q("DELETE FROM hook WHERE `file` = '%s' ",
dbesc($file)
);
return $r;
}
/**
* @brief Inserts a hook into a page request.
*
* Insert a short-lived hook into the running page request.
* Hooks are normally persistent so that they can be called
* across asynchronous processes such as delivery and poll
* processes.
*
* insert_hook lets you attach a hook callback immediately
* which will not persist beyond the life of this page request
* or the current process.
*
* @param string $hook
* name of hook to attach callback
* @param string $fn
* function name of callback handler
* @param int $version
* hook interface version, 0 uses two callback params, 1 uses one callback param
* @param int $priority
* currently not implemented in this function, would require the hook array to be resorted
*/
static public function insert($hook, $fn, $version = 0, $priority = 0) {
if(is_array($fn)) {
$fn = serialize($fn);
}
if(! is_array(App::$hooks))
App::$hooks = array();
if(! array_key_exists($hook, App::$hooks))
App::$hooks[$hook] = array();
App::$hooks[$hook][] = array('', $fn, $priority, $version);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Zotlabs\Identity\BasicId;
class BasicId {
private $name;
private $profile_photo;
private $profile_url;
private $address;
private $protocol;
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Zotlabs\Identity\ProfilePhoto;
class ProfilePhoto {
private $photo_large_url;
private $photo_medium_url;
private $photo_small_url;
private $photo_mimetype;
private $photo_updated;
}

View File

@@ -0,0 +1,93 @@
<?php
namespace Zotlabs\Module;
class Achievements extends \Zotlabs\Web\Controller {
function get() {
// This doesn't work, so
if (! is_developer())
return;
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
return;
}
$profile = 0;
$profile = argv(1);
profile_load($a,$which,$profile);
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['view_profile']) {
notice( t('Permission denied.') . EOL);
return;
}
$newmembertext = t('Some blurb about what to do when you\'re new here');
// By default, all badges are false
$contactbadge = false;
$profilebadge = false;
$keywordsbadge = false;
// Check number of contacts. Award a badge if over 10
// We'll figure these out on each page load instead of
// writing them to the DB because that will mean one needs
// to retain their achievements - eg, you can't add
// a bunch of channels just to get your badge, and then
// delete them all again. If these become popular or
// used in profiles or something, we may need to reconsider
// and add a table for this - because this won't scale.
$r = q("select * from abook where abook_channel = %d",
intval($owner)
);
if (count($r))
$contacts = count($r);
// We're checking for 11 to adjust for the abook record for self
if ($contacts >= 11)
$contactbadge = true;
// Check if an about field in the profile has been created.
$r = q("select * from profile where uid = %d and about <> ''",
intval($owner)
);
if ($r)
$profilebadge = 1;
// Check if keywords have been set
$r = q("select * from profile where uid = %d and keywords <> ''",
intval($owner)
);
if($r)
$keywordsbadge = 1;
return replace_macros(get_markup_template("achievements.tpl"), array(
'$newmembertext' => $newmembertext,
'$profilebadge' => $profilebadge,
'$contactbadge' => $contactbadge,
'$keywordsbadge' => $keywordsbadge,
'$channelsbadge' => $channelsbadge
));
}
}

314
Zotlabs/Module/Acl.php Normal file
View File

@@ -0,0 +1,314 @@
<?php
namespace Zotlabs\Module;
/* ACL selector json backend */
require_once("include/acl_selectors.php");
require_once("include/group.php");
class Acl extends \Zotlabs\Web\Controller {
function init(){
// 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);
// 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
if(x($_REQUEST,'query') && strlen($_REQUEST['query'])) {
if(! $type)
$type = 'm';
$search = $_REQUEST['query'];
}
if(!(local_channel()))
if(!($type == 'x' || $type == 'c'))
killme();
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, ";
$col = ((strpos($search,'@') !== false) ? 'xchan_addr' : 'xchan_name' );
$sql_extra3 = "AND $col like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
} else {
$sql_extra = $sql_extra2 = $sql_extra3 = "";
}
$groups = array();
$contacts = array();
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`
$sql_extra
GROUP BY `groups`.`id`
ORDER BY `groups`.`name`
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 ($type=='' || $type=='c') {
$extra_channels_sql = '';
// Only include channels who allow the observer to view their permissions
foreach($extra_channels as $channel) {
if(perm_is_allowed(intval($channel), get_observer_hash(),'view_contacts'))
$extra_channels_sql .= "," . intval($channel);
}
$extra_channels_sql = substr($extra_channels_sql,1); // Remove initial comma
// Getting info from the abook is better for local users because it contains info about permissions
if(local_channel()) {
if($extra_channels_sql != '')
$extra_channels_sql = " OR (abook_channel IN ($extra_channels_sql)) and abook_hidden = 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
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())
);
}
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
FROM xchan left join xlink on xlink_link = xchan_hash
WHERE xlink_xchan = '%s' AND xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" ,
dbesc(get_observer_hash())
);
// Find contacts of extra channels
// This is probably more complicated than it needs to be
if($extra_channels_sql) {
// Build a list of hashes that we got previously so we don't get them again
$known_hashes = array("'".get_observer_hash()."'");
if($r)
foreach($r as $rr)
$known_hashes[] = "'".$rr['hash']."'";
$known_hashes_sql = 'AND xchan_hash not in ('.join(',',$known_hashes).')';
$r2 = 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
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel IN ($extra_channels_sql) $known_hashes_sql AND abook_blocked = 0 and abook_pending = 0 and abook_hidden = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc");
if($r2)
$r = array_merge($r,$r2);
// Sort accoring to match position, then alphabetically. This could be avoided if the above two SQL queries could be combined into one, and the sorting could be done on the SQl server (like in the case of a local user)
$matchpos = function($x) use($search) {
$namepos = strpos($x['name'],$search);
$nickpos = strpos($x['nick'],$search);
// Use a large position if not found
return min($namepos === false ? 9999 : $namepos, $nickpos === false ? 9999 : $nickpos);
};
// This could be made simpler if PHP supported stable sorting
usort($r,function($a,$b) use($matchpos) {
$pos1 = $matchpos($a);
$pos2 = $matchpos($b);
if($pos1 == $pos2) { // Order alphabetically if match position is the same
if($a['name'] == $b['name'])
return 0;
else
return ($a['name'] < $b['name']) ? -1 : 1;
}
return ($pos1 < $pos2) ? -1 : 1;
});
}
}
if(intval(get_config('system','taganyone')) || intval(get_pconfig(local_channel(),'system','taganyone'))) {
if((count($r) < 100) && $type == 'c') {
$r2 = q("SELECT substr(xchan_hash,1,18) 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
FROM xchan
WHERE xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc"
);
if($r2)
$r = array_merge($r,$r2);
}
}
}
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
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)
and xchan_deleted = 0
$sql_extra3
ORDER BY `xchan_name` ASC ",
intval(local_channel()),
intval(PERMS_W_MAIL)
);
}
elseif(($type == 'a') || ($type == 'p')) {
$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
and xchan_deleted = 0
$sql_extra3
ORDER BY xchan_name ASC ",
intval(local_channel())
);
}
elseif($type == 'x') {
$r = $this->navbar_complete($a);
$contacts = array();
if($r) {
foreach($r as $g) {
$contacts[] = array(
"photo" => $g['photo'],
"name" => $g['name'],
"nick" => $g['address'],
);
}
}
$o = array(
'start' => $start,
'count' => $count,
'items' => $contacts,
);
echo json_encode($o);
killme();
}
else
$r = array();
if(count($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)) {
$contacts[] = array(
"type" => "c",
"photo" => "images/twopeople.png",
"name" => $g['name'] . '+',
"id" => $g['id'] . '+',
"xid" => $g['hash'],
"link" => $g['nick'],
"nick" => substr($g['nick'],0,strpos($g['nick'],'@')),
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
"taggable" => 'taggable',
"label" => t('network')
);
}
$contacts[] = array(
"type" => "c",
"photo" => $g['micro'],
"name" => $g['name'],
"id" => $g['id'],
"xid" => $g['hash'],
"link" => $g['nick'],
"nick" => (($g['nick']) ? substr($g['nick'],0,strpos($g['nick'],'@')) : t('RSS')),
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
"taggable" => '',
"label" => '',
);
}
}
$items = array_merge($groups, $contacts);
$o = array(
'start' => $start,
'count' => $count,
'items' => $items,
);
echo json_encode($o);
killme();
}
function navbar_complete(&$a) {
// logger('navbar_complete');
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
return;
}
$dirmode = intval(get_config('system','directory_mode'));
$search = ((x($_REQUEST,'search')) ? htmlentities($_REQUEST['search'],ENT_COMPAT,'UTF-8',false) : '');
if(! $search || mb_strlen($search) < 2)
return array();
$star = false;
$address = false;
if(substr($search,0,1) === '@')
$search = substr($search,1);
if(substr($search,0,1) === '*') {
$star = true;
$search = substr($search,1);
}
if(strpos($search,'@') !== false) {
$address = true;
}
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
$url = z_root() . '/dirsearch';
}
if(! $url) {
require_once("include/dir_fns.php");
$directory = find_upstream_directory($dirmode);
$url = $directory['url'] . '/dirsearch';
}
$count = (x($_REQUEST,'count')?$_REQUEST['count']:100);
if($url) {
$query = $url . '?f=' ;
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode($search) : '');
$x = z_fetch_url($query);
if($x['success']) {
$t = 0;
$j = json_decode($x['body'],true);
if($j && $j['results']) {
return $j['results'];
}
}
}
return array();
}
}

2060
Zotlabs/Module/Admin.php Normal file

File diff suppressed because it is too large Load Diff

122
Zotlabs/Module/Api.php Normal file
View File

@@ -0,0 +1,122 @@
<?php
namespace Zotlabs\Module;
require_once('include/api.php');
class Api extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if(count(\App::$user) && x(\App::$user,'uid') && \App::$user['uid'] != local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
}
function get() {
if(\App::$cmd=='api/oauth/authorize'){
/*
* api/oauth/authorize interact with the user. return a standard page
*/
\App::$page['template'] = "minimal";
// get consumer/client from request token
try {
$request = OAuth1Request::from_request();
} catch(Exception $e) {
echo "<pre>"; var_dump($e); killme();
}
if(x($_POST,'oauth_yes')){
$app = $this->oauth_get_client($request);
if (is_null($app)) return "Invalid request. Unknown token.";
$consumer = new OAuth1Consumer($app['client_id'], $app['pw'], $app['redirect_uri']);
$verifier = md5($app['secret'].local_channel());
set_config("oauth", $verifier, local_channel());
if($consumer->callback_url!=null) {
$params = $request->get_parameters();
$glue="?";
if (strstr($consumer->callback_url,$glue)) $glue="?";
goaway($consumer->callback_url . $glue . "oauth_token=" . OAuth1Util::urlencode_rfc3986($params['oauth_token']) . "&oauth_verifier=" . OAuth1Util::urlencode_rfc3986($verifier));
killme();
}
$tpl = get_markup_template("oauth_authorize_done.tpl");
$o = replace_macros($tpl, array(
'$title' => t('Authorize application connection'),
'$info' => t('Return to your app and insert this Securty Code:'),
'$code' => $verifier,
));
return $o;
}
if(! local_channel()) {
//TODO: we need login form to redirect to this page
notice( t('Please login to continue.') . EOL );
return login(false,'api-login',$request->get_parameters());
}
//FKOAuth1::loginUser(4);
$app = $this->oauth_get_client($request);
if (is_null($app)) return "Invalid request. Unknown token.";
$tpl = get_markup_template('oauth_authorize.tpl');
$o = replace_macros($tpl, array(
'$title' => t('Authorize application connection'),
'$app' => $app,
'$authorize' => t('Do you want to authorize this application to access your posts and contacts, and/or create new posts for you?'),
'$yes' => t('Yes'),
'$no' => t('No'),
));
//echo "<pre>"; var_dump($app); killme();
return $o;
}
echo api_call($a);
killme();
}
function oauth_get_client($request){
$params = $request->get_parameters();
$token = $params['oauth_token'];
$r = q("SELECT `clients`.*
FROM `clients`, `tokens`
WHERE `clients`.`client_id`=`tokens`.`client_id`
AND `tokens`.`id`='%s' AND `tokens`.`scope`='request'",
dbesc($token));
if (!count($r))
return null;
return $r[0];
}
}

130
Zotlabs/Module/Appman.php Normal file
View File

@@ -0,0 +1,130 @@
<?php /** @file */
namespace Zotlabs\Module;
require_once('include/apps.php');
class Appman extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
if($_POST['url']) {
$arr = array(
'uid' => intval($_REQUEST['uid']),
'url' => escape_tags($_REQUEST['url']),
'guid' => escape_tags($_REQUEST['guid']),
'author' => escape_tags($_REQUEST['author']),
'addr' => escape_tags($_REQUEST['addr']),
'name' => escape_tags($_REQUEST['name']),
'desc' => escape_tags($_REQUEST['desc']),
'photo' => escape_tags($_REQUEST['photo']),
'version' => escape_tags($_REQUEST['version']),
'price' => escape_tags($_REQUEST['price']),
'requires' => escape_tags($_REQUEST['requires']),
'system' => intval($_REQUEST['system']),
'sig' => escape_tags($_REQUEST['sig']),
'categories' => escape_tags($_REQUEST['categories'])
);
$_REQUEST['appid'] = app_install(local_channel(),$arr);
if(app_installed(local_channel(),$arr))
info( t('App installed.') . EOL);
return;
}
$papp = app_decode($_POST['papp']);
if(! is_array($papp)) {
notice( t('Malformed app.') . EOL);
return;
}
if($_POST['install']) {
app_install(local_channel(),$papp);
if(app_installed(local_channel(),$papp))
info( t('App installed.') . EOL);
}
if($_POST['delete']) {
app_destroy(local_channel(),$papp);
}
if($_POST['edit']) {
return;
}
if($_SESSION['return_url'])
goaway(z_root() . '/' . $_SESSION['return_url']);
goaway(z_root() . '/apps');
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$channel = \App::get_channel();
$app = null;
$embed = null;
if($_REQUEST['appid']) {
$r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($_REQUEST['appid']),
dbesc(local_channel())
);
if($r) {
$app = $r[0];
$term = q("select * from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($r[0]['id'])
);
if($term) {
$app['categories'] = '';
foreach($term as $t) {
if($app['categories'])
$app['categories'] .= ',';
$app['categories'] .= $t['term'];
}
}
}
$embed = array('embed', t('Embed code'), app_encode($app,true),'', 'onclick="this.select();"');
}
return replace_macros(get_markup_template('app_create.tpl'), array(
'$banner' => (($app) ? t('Edit App') : t('Create App')),
'$app' => $app,
'$guid' => (($app) ? $app['app_id'] : ''),
'$author' => (($app) ? $app['app_author'] : $channel['channel_hash']),
'$addr' => (($app) ? $app['app_addr'] : $channel['xchan_addr']),
'$name' => array('name', t('Name of app'),(($app) ? $app['app_name'] : ''), t('Required')),
'$url' => array('url', t('Location (URL) of app'),(($app) ? $app['app_url'] : ''), t('Required')),
'$desc' => array('desc', t('Description'),(($app) ? $app['app_desc'] : ''), ''),
'$photo' => array('photo', t('Photo icon URL'),(($app) ? $app['app_photo'] : ''), t('80 x 80 pixels - optional')),
'$categories' => array('categories',t('Categories (optional, comma separated list)'),(($app) ? $app['categories'] : ''),''),
'$version' => array('version', t('Version ID'),(($app) ? $app['app_version'] : ''), ''),
'$price' => array('price', t('Price of app'),(($app) ? $app['app_price'] : ''), ''),
'$page' => array('page', t('Location (URL) to purchase app'),(($app) ? $app['app_page'] : ''), ''),
'$system' => (($app) ? intval($app['app_system']) : 0),
'$requires' => (($app) ? $app['app_requires'] : ''),
'$embed' => $embed,
'$submit' => t('Submit')
));
}
}

52
Zotlabs/Module/Apps.php Normal file
View File

@@ -0,0 +1,52 @@
<?php
namespace Zotlabs\Module;
require_once('include/apps.php');
class Apps extends \Zotlabs\Web\Controller {
function get() {
if(argc() == 2 && argv(1) == 'edit')
$mode = 'edit';
else
$mode = 'list';
$_SESSION['return_url'] = \App::$cmd;
$apps = array();
if(local_channel()) {
import_system_apps();
$syslist = array();
$list = app_list(local_channel(), false, $_GET['cat']);
if($list) {
foreach($list as $x) {
$syslist[] = app_encode($x);
}
}
translate_system_apps($syslist);
}
else
$syslist = get_system_apps(true);
usort($syslist,'app_name_compare');
// logger('apps: ' . print_r($syslist,true));
foreach($syslist as $app) {
$apps[] = app_render($app,$mode);
}
return replace_macros(get_markup_template('myapps.tpl'), array(
'$sitename' => get_config('system','sitename'),
'$cat' => ((array_key_exists('cat',$_GET) && $_GET['cat']) ? ' - ' . escape_tags($_GET['cat']) : ''),
'$title' => t('Apps'),
'$apps' => $apps,
));
}
}

61
Zotlabs/Module/Attach.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
namespace Zotlabs\Module;
require_once('include/security.php');
require_once('include/attach.php');
class Attach extends \Zotlabs\Web\Controller {
function init() {
if(argc() < 2) {
notice( t('Item not available.') . EOL);
return;
}
$r = attach_by_hash(argv(1),((argc() > 2) ? intval(argv(2)) : 0));
if(! $r['success']) {
notice( $r['message'] . EOL);
return;
}
$c = q("select channel_address from channel where channel_id = %d limit 1",
intval($r['data']['uid'])
);
if(! $c)
return;
$unsafe_types = array('text/html','text/css','application/javascript');
if(in_array($r['data']['filetype'],$unsafe_types)) {
header('Content-type: text/plain');
}
else {
header('Content-type: ' . $r['data']['filetype']);
}
header('Content-disposition: attachment; filename="' . $r['data']['filename'] . '"');
if(intval($r['data']['os_storage'])) {
$fname = dbunescbin($r['data']['data']);
if(strpos($fname,'store') !== false)
$istream = fopen($fname,'rb');
else
$istream = fopen('store/' . $c[0]['channel_address'] . '/' . $fname,'rb');
$ostream = fopen('php://output','wb');
if($istream && $ostream) {
pipe_streams($istream,$ostream);
fclose($istream);
fclose($ostream);
}
}
else
echo dbunescbin($r['data']['data']);
killme();
}
}

View File

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

92
Zotlabs/Module/Block.php Normal file
View File

@@ -0,0 +1,92 @@
<?php
namespace Zotlabs\Module;
require_once('include/items.php');
require_once('include/conversation.php');
require_once('include/page_widgets.php');
class Block extends \Zotlabs\Web\Controller {
function init() {
$which = argv(1);
$profile = 0;
profile_load($a,$which,$profile);
if(\App::$profile['profile_uid'])
head_set_icon(\App::$profile['thumb']);
}
function get() {
if(! perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'view_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
if(argc() < 3) {
notice( t('Invalid item.') . EOL);
return;
}
$channel_address = argv(1);
$page_id = argv(2);
$u = q("select channel_id from channel where channel_address = '%s' limit 1",
dbesc($channel_address)
);
if(! $u) {
notice( t('Channel not found.') . EOL);
return;
}
if($_REQUEST['rev'])
$revision = " and revision = " . intval($_REQUEST['rev']) . " ";
else
$revision = " order by revision desc ";
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
item_type = %d $sql_options $revision limit 1",
intval($u[0]['channel_id']),
dbesc($page_id),
intval(ITEM_TYPE_BLOCK)
);
if(! $r) {
// 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
item_type = %d $revision limit 1",
intval($u[0]['channel_id']),
dbesc($page_id),
intval(ITEM_TYPE_BLOCK)
);
if($x) {
// Yes, it's there. You just aren't allowed to see it.
notice( t('Permission denied.') . EOL);
}
else {
notice( t('Page not found.') . EOL);
}
return;
}
xchan_query($r);
$r = fetch_post_tags($r,true);
$o .= prepare_page($r[0]);
return $o;
}
}

170
Zotlabs/Module/Blocks.php Normal file
View File

@@ -0,0 +1,170 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
class Blocks extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$_SESSION['return_url'] = \App::$query_string;
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
// Block design features from visitors
if((! $uid) || ($uid != $owner)) {
notice( t('Permission denied.') . EOL);
return;
}
$mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype'));
$x = array(
'webpage' => ITEM_TYPE_BLOCK,
'is_owner' => true,
'nickname' => \App::$profile['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'bang' => '',
'showacl' => false,
'visitor' => true,
'mimetype' => $mimetype,
'mimeselect' => true,
'hide_location' => true,
'ptlabel' => t('Block Name'),
'profile_uid' => intval($owner),
'expanded' => true,
'novoting' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
if($_REQUEST['pagetitle'])
$x['pagetitle'] = $_REQUEST['pagetitle'];
$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",
intval($owner),
intval(ITEM_TYPE_BLOCK)
);
$pages = null;
if($r) {
$pages = array();
foreach($r as $rr) {
$element_arr = array(
'type' => 'block',
'title' => $rr['title'],
'body' => $rr['body'],
'created' => $rr['created'],
'edited' => $rr['edited'],
'mimetype' => $rr['mimetype'],
'pagetitle' => $rr['sid'],
'mid' => $rr['mid']
);
$pages[$rr['iid']][] = array(
'url' => $rr['iid'],
'name' => $rr['sid'],
'title' => $rr['title'],
'created' => $rr['created'],
'edited' => $rr['edited'],
'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]'
);
}
}
//Build the base URL for edit links
$url = z_root() . '/editblock/' . $which;
$o .= replace_macros(get_markup_template('blocklist.tpl'), array(
'$baseurl' => $url,
'$title' => t('Blocks'),
'$name' => t('Block Name'),
'$blocktitle' => t('Block Title'),
'$created' => t('Created'),
'$edited' => t('Edited'),
'$create' => t('Create'),
'$edit' => t('Edit'),
'$share' => t('Share'),
'$delete' => t('Delete'),
'$editor' => $editor,
'$pages' => $pages,
'$channel' => $which,
'$view' => t('View'),
'$preview' => '1',
));
return $o;
}
}

View File

@@ -0,0 +1,105 @@
<?php
namespace Zotlabs\Module;
class Bookmarks extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
$item_id = intval($_REQUEST['item']);
$burl = trim($_REQUEST['burl']);
if(! $item_id)
return;
$u = \App::get_channel();
$item_normal = item_normal();
$i = q("select * from item where id = %d and uid = %d $item_normal limit 1",
intval($item_id),
intval(local_channel())
);
if(! $i)
return;
$i = fetch_post_tags($i);
$item = $i[0];
$terms = get_terms_oftype($item['term'],TERM_BOOKMARK);
if($terms) {
require_once('include/bookmarks.php');
$s = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['author_xchan'])
);
if(! $s) {
logger('mod_bookmarks: author lookup failed.');
killme();
}
foreach($terms as $t) {
if($burl) {
if($burl == $t['url']) {
bookmark_add($u,$s[0],$t,$item['item_private']);
}
}
else
bookmark_add($u,$s[0],$t,$item['item_private']);
info( t('Bookmark added') . EOL);
}
}
killme();
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
require_once('include/menu.php');
require_once('include/conversation.php');
$channel = \App::get_channel();
$o = profile_tabs($a,true,$channel['channel_address']);
$o .= '<div class="generic-content-wrapper-styled">';
$o .= '<h3>' . t('My Bookmarks') . '</h3>';
$x = menu_list(local_channel(),'',MENU_BOOKMARK);
if($x) {
foreach($x as $xx) {
$y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash());
$o .= menu_render($y,'',true);
}
}
$o .= '<h3>' . t('My Connections Bookmarks') . '</h3>';
$x = menu_list(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
if($x) {
foreach($x as $xx) {
$y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash());
$o .= menu_render($y,'',true);
}
}
$o .= '</div>';
return $o;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Zotlabs\Module;
class Branchtopic extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
$item_id = 0;
if(argc() > 1)
$item_id = intval(argv(1));
if(! $item_id)
return;
$channel = \App::get_channel();
if(! $channel)
return;
$r = q("select * from item where id = %d and uid = %d and owner_xchan = '%s' and id != parent limit 1",
intval($item_id),
intval(local_channel()),
dbesc($channel['channel_hash'])
);
if(! $r)
return;
$p = q("select * from item where id = %d and uid = %d limit 1",
intval($r[0]['parent']),
intval(local_channel())
);
$x = q("update item set parent = id, route = '', item_thread_top = 1 where id = %d",
intval($item_id)
);
return;
}
}

357
Zotlabs/Module/Cal.php Normal file
View File

@@ -0,0 +1,357 @@
<?php
namespace Zotlabs\Module;
require_once('include/conversation.php');
require_once('include/bbcode.php');
require_once('include/datetime.php');
require_once('include/event.php');
require_once('include/items.php');
require_once('include/Contact.php');
class Cal extends \Zotlabs\Web\Controller {
function init() {
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
return;
}
$o = '';
if(argc() > 1) {
$nick = argv(1);
profile_load($a,$nick);
$channelx = channelx_by_nick($nick);
if(! $channelx)
return;
\App::$data['channel'] = $channelx;
$observer = \App::get_observer();
\App::$data['observer'] = $observer;
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
head_set_icon(\App::$data['channel']['xchan_photo_s']);
\App::$page['htmlhead'] .= "<script> var profile_uid = " . ((\App::$data['channel']) ? \App::$data['channel']['channel_id'] : 0) . "; </script>" ;
}
return;
}
function get() {
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
return;
}
$channel = null;
if(argc() > 1) {
$channel = channelx_by_nick(argv(1));
}
if(! $channel) {
notice( t('Channel not found.') . EOL);
return;
}
// since we don't currently have an event permission - use the stream permission
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) {
notice( t('Permissions denied.') . EOL);
return;
}
$sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event');
$first_day = get_pconfig(local_channel(),'system','cal_first_day');
$first_day = (($first_day) ? $first_day : 0);
$htpl = get_markup_template('event_head.tpl');
\App::$page['htmlhead'] .= replace_macros($htpl,array(
'$baseurl' => z_root(),
'$module_url' => '/cal/' . $channel['channel_address'],
'$modparams' => 2,
'$lang' => \App::$language,
'$first_day' => $first_day
));
$o = '';
$tabs = profile_tabs($a, True, $channel['channel_address']);
$mode = 'view';
$y = 0;
$m = 0;
$ignored = ((x($_REQUEST,'ignored')) ? " and ignored = " . intval($_REQUEST['ignored']) . " " : '');
// logger('args: ' . print_r(\App::$argv,true));
if(argc() > 3 && intval(argv(2)) && intval(argv(3))) {
$mode = 'view';
$y = intval(argv(2));
$m = intval(argv(3));
}
if(argc() <= 3) {
$mode = 'view';
$event_id = argv(2);
}
if($mode == 'view') {
/* edit/create form */
if($event_id) {
$r = q("SELECT * FROM `event` WHERE event_hash = '%s' AND `uid` = %d LIMIT 1",
dbesc($event_id),
intval($channel['channel_id'])
);
if(count($r))
$orig_event = $r[0];
}
// Passed parameters overrides anything found in the DB
if(!x($orig_event))
$orig_event = array();
$tz = date_default_timezone_get();
if(x($orig_event))
$tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC');
$syear = datetime_convert('UTC', $tz, $sdt, 'Y');
$smonth = datetime_convert('UTC', $tz, $sdt, 'm');
$sday = datetime_convert('UTC', $tz, $sdt, 'd');
$shour = datetime_convert('UTC', $tz, $sdt, 'H');
$sminute = datetime_convert('UTC', $tz, $sdt, 'i');
$stext = datetime_convert('UTC',$tz,$sdt);
$stext = substr($stext,0,14) . "00:00";
$fyear = datetime_convert('UTC', $tz, $fdt, 'Y');
$fmonth = datetime_convert('UTC', $tz, $fdt, 'm');
$fday = datetime_convert('UTC', $tz, $fdt, 'd');
$fhour = datetime_convert('UTC', $tz, $fdt, 'H');
$fminute = datetime_convert('UTC', $tz, $fdt, 'i');
$ftext = datetime_convert('UTC',$tz,$fdt);
$ftext = substr($ftext,0,14) . "00:00";
$type = ((x($orig_event)) ? $orig_event['type'] : 'event');
$f = get_config('system','event_input_format');
if(! $f)
$f = 'ymd';
$catsenabled = feature_enabled($channel['channel_id'],'categories');
$show_bd = perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts');
if(! $show_bd) {
$sql_extra .= " and event.type != 'birthday' ";
}
$category = '';
$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
if(! $y)
$y = intval($thisyear);
if(! $m)
$m = intval($thismonth);
// Put some limits on dates. The PHP date functions don't seem to do so well before 1900.
// An upper limit was chosen to keep search engines from exploring links millions of years in the future.
if($y < 1901)
$y = 1900;
if($y > 2099)
$y = 2100;
$nextyear = $y;
$nextmonth = $m + 1;
if($nextmonth > 12) {
$nextmonth = 1;
$nextyear ++;
}
$prevyear = $y;
if($m > 1)
$prevmonth = $m - 1;
else {
$prevmonth = 12;
$prevyear --;
}
$dim = get_dim($y,$m);
$start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0);
$finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59);
if (argv(2) === 'json'){
if (x($_GET,'start')) $start = $_GET['start'];
if (x($_GET,'end')) $finish = $_GET['end'];
}
$start = datetime_convert('UTC','UTC',$start);
$finish = datetime_convert('UTC','UTC',$finish);
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
if (x($_GET,'id')){
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d $sql_extra limit 1",
intval($channel['channel_id']),
intval($_GET['id'])
);
}
else {
// fixed an issue with "nofinish" events not showing up in the calendar.
// There's still an issue if the finish date crosses the end of month.
// Noting this for now - it will need to be fixed here and in Friendica.
// Ultimately the finish date shouldn't be involved in the query.
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
from event left join item on event_hash = resource_id
where resource_type = 'event' and event.uid = %d $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 ",
intval($channel['channel_id']),
dbesc($start),
dbesc($finish),
dbesc($adjust_start),
dbesc($adjust_finish)
);
}
$links = array();
if($r) {
xchan_query($r);
$r = fetch_post_tags($r,true);
$r = sort_by_date($r);
}
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j'));
if(! x($links,$j))
$links[$j] = z_root() . '/' . \App::$cmd . '#link-' . $j;
}
}
$events=array();
$last_date = '';
$fmt = t('l, F j');
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['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));
$d = day_translate($d);
$start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'c') : datetime_convert('UTC','UTC',$rr['start'],'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'));
}
$is_first = ($d !== $last_date);
$last_date = $d;
$edit = false;
$drop = false;
$title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8'));
if(! $title) {
list($title, $_trash) = explode("<br",bbcode($rr['desc']),2);
$title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8'));
}
$html = format_event_html($rr);
$rr['desc'] = bbcode($rr['desc']);
$rr['location'] = bbcode($rr['location']);
$events[] = array(
'id'=>$rr['id'],
'hash' => $rr['event_hash'],
'start'=> $start,
'end' => $end,
'drop' => $drop,
'allDay' => false,
'title' => $title,
'j' => $j,
'd' => $d,
'edit' => $edit,
'is_first'=>$is_first,
'item'=>$rr,
'html'=>$html,
'plink' => array($rr['plink'],t('Link to Source'),'',''),
);
}
}
if (argv(2) === 'json'){
echo json_encode($events); killme();
}
// links: array('href', 'text', 'extra css classes', 'title')
if (x($_GET,'id')){
$tpl = get_markup_template("event_cal.tpl");
}
else {
$tpl = get_markup_template("events_cal-js.tpl");
}
$nick = $channel['channel_address'];
$o = replace_macros($tpl, array(
'$baseurl' => z_root(),
'$new_event' => array(z_root().'/cal',(($event_id) ? t('Edit Event') : t('Create Event')),'',''),
'$previus' => array(z_root()."/cal/$nick/$prevyear/$prevmonth",t('Previous'),'',''),
'$next' => array(z_root()."/cal/$nick/$nextyear/$nextmonth",t('Next'),'',''),
'$export' => array(z_root()."/cal/$nick/$y/$m/export",t('Export'),'',''),
'$calendar' => cal($y,$m,$links, ' eventcal'),
'$events' => $events,
'$upload' => t('Import'),
'$submit' => t('Submit'),
'$prev' => t('Previous'),
'$next' => t('Next'),
'$today' => t('Today'),
'$form' => $form,
'$expandform' => ((x($_GET,'expandform')) ? true : false),
'$tabs' => $tabs
));
if (x($_GET,'id')){ echo $o; killme(); }
return $o;
}
}
}

365
Zotlabs/Module/Channel.php Normal file
View File

@@ -0,0 +1,365 @@
<?php
namespace Zotlabs\Module;
require_once('include/contact_widgets.php');
require_once('include/items.php');
require_once("include/bbcode.php");
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() {
$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);
}
\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) {
if($load)
$_SESSION['loadtime'] = datetime_convert();
$checkjs = new \Zotlabs\Web\CheckJS(1);
$category = $datequery = $datequery2 = '';
$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']) : '');
if(get_config('system','block_public') && (! get_account_id()) && (! remote_channel())) {
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);
$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']
);
}
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, \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";
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 ($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),
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 {
if($parents_str) {
$update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )";
}
}
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;
}
}

110
Zotlabs/Module/Chanview.php Normal file
View File

@@ -0,0 +1,110 @@
<?php
namespace Zotlabs\Module;
require_once('include/Contact.php');
require_once('include/zot.php');
class Chanview extends \Zotlabs\Web\Controller {
function get() {
$observer = \App::get_observer();
$xchan = null;
$r = null;
if($_REQUEST['hash']) {
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($_REQUEST['hash'])
);
}
if($_REQUEST['address']) {
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
dbesc($_REQUEST['address'])
);
}
elseif(local_channel() && intval($_REQUEST['cid'])) {
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
intval(local_channel()),
intval($_REQUEST['cid'])
);
}
elseif($_REQUEST['url']) {
// if somebody re-installed they will have more than one xchan, use the most recent name date as this is
// the most useful consistently ascending table item we have.
$r = q("select * from xchan where xchan_url = '%s' order by xchan_name_date desc limit 1",
dbesc($_REQUEST['url'])
);
}
if($r) {
\App::$poi = $r[0];
}
// Here, let's see if we have an xchan. If we don't, how we proceed is determined by what
// info we do have. If it's a URL, we can offer to visit it directly. If it's a webbie or
// address, we can and should try to import it. If it's just a hash, we can't continue, but we
// probably wouldn't have a hash if we don't already have an xchan for this channel.
if(! \App::$poi) {
logger('mod_chanview: fallback');
// This is hackish - construct a zot address from the url
if($_REQUEST['url']) {
if(preg_match('/https?\:\/\/(.*?)(\/channel\/|\/profile\/)(.*?)$/ism',$_REQUEST['url'],$matches)) {
$_REQUEST['address'] = $matches[3] . '@' . $matches[1];
}
logger('mod_chanview: constructed address ' . print_r($matches,true));
}
if($_REQUEST['address']) {
$ret = zot_finger($_REQUEST['address'],null);
if($ret['success']) {
$j = json_decode($ret['body'],true);
if($j)
import_xchan($j);
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
dbesc($_REQUEST['address'])
);
if($r)
\App::$poi = $r[0];
}
}
}
if(! \App::$poi) {
// We don't know who this is, and we can't figure it out from the URL
// On the plus side, there's a good chance we know somebody else at that
// hub so sending them there with a Zid will probably work anyway.
$url = ($_REQUEST['url']);
if($observer)
$url = zid($url);
}
if (\App::$poi) {
$url = \App::$poi['xchan_url'];
if($observer)
$url = zid($url);
}
// let somebody over-ride the iframed viewport presentation
// or let's just declare this a failed experiment.
// if((! local_channel()) || (get_pconfig(local_channel(),'system','chanview_full')))
goaway($url);
// $o = replace_macros(get_markup_template('chanview.tpl'),array(
// '$url' => $url,
// '$full' => t('toggle full screen mode')
// ));
// return $o;
}
}

261
Zotlabs/Module/Chat.php Normal file
View File

@@ -0,0 +1,261 @@
<?php
namespace Zotlabs\Module; /** @file */
require_once('include/chat.php');
require_once('include/bookmarks.php');
class Chat extends \Zotlabs\Web\Controller {
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 = $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);
}
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $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 post() {
if($_POST['room_name'])
$room = strip_tags(trim($_POST['room_name']));
if((! $room) || (! local_channel()))
return;
$channel = \App::get_channel();
if($_POST['action'] === 'drop') {
logger('delete chatroom');
chatroom_destroy($channel,array('cr_name' => $room));
goaway(z_root() . '/chat/' . $channel['channel_address']);
}
$acl = new \Zotlabs\Access\AccessList($channel);
$acl->set_from_array($_REQUEST);
$arr = $acl->get();
$arr['name'] = $room;
$arr['expire'] = intval($_POST['chat_expire']);
if(intval($arr['expire']) < 0)
$arr['expire'] = 0;
chatroom_create($channel,$arr);
$x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1",
dbesc($room),
intval(local_channel())
);
build_sync_packet(0, array('chatroom' => $x));
if($x)
goaway(z_root() . '/chat/' . $channel['channel_address'] . '/' . $x[0]['cr_id']);
// that failed. Try again perhaps?
goaway(z_root() . '/chat/' . $channel['channel_address'] . '/new');
}
function get() {
if(local_channel())
$channel = \App::get_channel();
$ob = \App::get_observer();
$observer = get_observer_hash();
if(! $observer) {
notice( t('Permission denied.') . EOL);
return;
}
if(! perm_is_allowed(\App::$profile['profile_uid'],$observer,'chat')) {
notice( t('Permission denied.') . EOL);
return;
}
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'leave')) {
chatroom_leave($observer,argv(2),$_SERVER['REMOTE_ADDR']);
goaway(z_root() . '/channel/' . argv(1));
}
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'status')) {
$ret = array('success' => false);
$room_id = intval(argv(2));
if(! $room_id || ! $observer)
return;
$r = q("select * from chatroom where cr_id = %d limit 1",
intval($room_id)
);
if(! $r) {
json_return_and_die($ret);
}
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) {
json_return_and_die($ret);
}
$y = q("select count(*) as total from chatpresence where cp_room = %d",
intval($room_id)
);
if($y) {
$ret['success'] = true;
$ret['chatroom'] = $r[0]['cr_name'];
$ret['inroom'] = $y[0]['total'];
}
// figure out how to present a timestamp of the last activity, since we don't know the observer's timezone.
$z = q("select created from chat where chat_room = %d order by created desc limit 1",
intval($room_id)
);
if($z) {
$ret['last'] = $z[0]['created'];
}
json_return_and_die($ret);
}
if(argc() > 2 && intval(argv(2))) {
$room_id = intval(argv(2));
$bookmark_link = get_bookmark_link($ob);
$x = chatroom_enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']);
if(! $x)
return;
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
intval($room_id),
intval(\App::$profile['profile_uid'])
);
if($x) {
$acl = new \Zotlabs\Access\AccessList(false);
$acl->set($x[0]);
$private = $acl->is_private();
$room_name = $x[0]['cr_name'];
if($bookmark_link)
$bookmark_link .= '&url=' . z_root() . '/chat/' . argv(1) . '/' . argv(2) . '&title=' . urlencode($x[0]['cr_name']) . (($private) ? '&private=1' : '') . '&ischat=1';
}
else {
notice( t('Room not found') . EOL);
return;
}
$cipher = get_pconfig(local_channel(),'system','default_cipher');
if(! $cipher)
$cipher = 'aes256';
$o = replace_macros(get_markup_template('chat.tpl'),array(
'$is_owner' => ((local_channel() && local_channel() == $x[0]['cr_uid']) ? true : false),
'$room_name' => $room_name,
'$room_id' => $room_id,
'$baseurl' => z_root(),
'$nickname' => argv(1),
'$submit' => t('Submit'),
'$leave' => t('Leave Room'),
'$drop' => t('Delete Room'),
'$away' => t('I am away right now'),
'$online' => t('I am online'),
'$bookmark_link' => $bookmark_link,
'$bookmark' => t('Bookmark this room'),
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
'$cipher' => $cipher,
'$linkurl' => t('Please enter a link URL:'),
'$encrypt' => t('Encrypt text'),
'$insert' => t('Insert web link')
));
return $o;
}
require_once('include/conversation.php');
$o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']);
if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) {
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(
'$header' => t('New Chatroom'),
'$name' => array('room_name',t('Chatroom name'),'', ''),
'$chat_expire' => array('chat_expire',t('Expiration of chats (minutes)'),120,''),
'$permissions' => t('Permissions'),
'$acl' => populate_acl($channel_acl,false),
'$lockstate' => $lockstate,
'$submit' => t('Submit')
));
}
$rooms = chatroom_list(\App::$profile['profile_uid']);
$o .= replace_macros(get_markup_template('chatrooms.tpl'), array(
'$header' => sprintf( t('%1$s\'s Chatrooms'), \App::$profile['name']),
'$name' => t('Name'),
'$baseurl' => z_root(),
'$nickname' => \App::$profile['channel_address'],
'$rooms' => $rooms,
'$norooms' => t('No chatrooms available'),
'$newroom' => t('Create New'),
'$is_owner' => ((local_channel() && local_channel() == \App::$profile['profile_uid']) ? 1 : 0),
'$chatroom_new' => $chatroom_new,
'$expire' => t('Expiration'),
'$expire_unit' => t('min') //minutes
));
return $o;
}
}

168
Zotlabs/Module/Chatsvc.php Normal file
View File

@@ -0,0 +1,168 @@
<?php
namespace Zotlabs\Module; /** @file */
require_once('include/security.php');
class Chatsvc extends \Zotlabs\Web\Controller {
function init() {
//logger('chatsvc');
$ret = array('success' => false);
\App::$data['chat']['room_id'] = intval($_REQUEST['room_id']);
$x = q("select cr_uid from chatroom where cr_id = %d and cr_id != 0 limit 1",
intval(\App::$data['chat']['room_id'])
);
if(! $x)
json_return_and_die($ret);
\App::$data['chat']['uid'] = $x[0]['cr_uid'];
if(! perm_is_allowed(\App::$data['chat']['uid'],get_observer_hash(),'chat')) {
json_return_and_die($ret);
}
}
function post() {
$ret = array('success' => false);
$room_id = \App::$data['chat']['room_id'];
$text = escape_tags($_REQUEST['chat_text']);
if(! $text)
return;
$sql_extra = permissions_sql(\App::$data['chat']['uid']);
$r = q("select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
intval(\App::$data['chat']['uid']),
intval(\App::$data['chat']['room_id'])
);
if(! $r)
json_return_and_die($ret);
$arr = array(
'chat_room' => \App::$data['chat']['room_id'],
'chat_xchan' => get_observer_hash(),
'chat_text' => $text
);
call_hooks('chat_post',$arr);
$x = q("insert into chat ( chat_room, chat_xchan, created, chat_text )
values( %d, '%s', '%s', '%s' )",
intval(\App::$data['chat']['room_id']),
dbesc(get_observer_hash()),
dbesc(datetime_convert()),
dbesc($arr['chat_text'])
);
$ret['success'] = true;
json_return_and_die($ret);
}
function get() {
$status = strip_tags($_REQUEST['status']);
$room_id = intval(\App::$data['chat']['room_id']);
$stopped = ((x($_REQUEST,'stopped') && intval($_REQUEST['stopped'])) ? true : false);
if($status && $room_id) {
$x = q("select channel_address from channel where channel_id = %d limit 1",
intval(\App::$data['chat']['uid'])
);
$r = q("update chatpresence set cp_status = '%s', cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s'",
dbesc($status),
dbesc(datetime_convert()),
intval($room_id),
dbesc(get_observer_hash()),
dbesc($_SERVER['REMOTE_ADDR'])
);
goaway(z_root() . '/chat/' . $x[0]['channel_address'] . '/' . $room_id);
}
if(! $stopped) {
$lastseen = intval($_REQUEST['last']);
$ret = array('success' => false);
$sql_extra = permissions_sql(\App::$data['chat']['uid']);
$r = q("select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
intval(\App::$data['chat']['uid']),
intval(\App::$data['chat']['room_id'])
);
if(! $r)
json_return_and_die($ret);
$inroom = array();
$r = q("select * from chatpresence left join xchan on xchan_hash = cp_xchan where cp_room = %d order by xchan_name",
intval(\App::$data['chat']['room_id'])
);
if($r) {
foreach($r as $rr) {
switch($rr['cp_status']) {
case 'away':
$status = t('Away');
$status_class = 'away';
break;
case 'online':
default:
$status = t('Online');
$status_class = 'online';
break;
}
$inroom[] = array('img' => zid($rr['xchan_photo_m']), 'img_type' => $rr['xchan_photo_mimetype'],'name' => $rr['xchan_name'], 'status' => $status, 'status_class' => $status_class);
}
}
$chats = array();
$r = q("select * from chat left join xchan on chat_xchan = xchan_hash where chat_room = %d and chat_id > %d order by created",
intval(\App::$data['chat']['room_id']),
intval($lastseen)
);
if($r) {
foreach($r as $rr) {
$chats[] = array(
'id' => $rr['chat_id'],
'img' => zid($rr['xchan_photo_m']),
'img_type' => $rr['xchan_photo_mimetype'],
'name' => $rr['xchan_name'],
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $rr['created'], 'c'),
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $rr['created'], 'r'),
'text' => smilies(bbcode($rr['chat_text'])),
'self' => ((get_observer_hash() == $rr['chat_xchan']) ? 'self' : '')
);
}
}
}
$r = q("update chatpresence set cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s'",
dbesc(datetime_convert()),
intval(\App::$data['chat']['room_id']),
dbesc(get_observer_hash()),
dbesc($_SERVER['REMOTE_ADDR'])
);
$ret['success'] = true;
if(! $stopped) {
$ret['inroom'] = $inroom;
$ret['chats'] = $chats;
}
json_return_and_die($ret);
}
}

109
Zotlabs/Module/Cloud.php Normal file
View File

@@ -0,0 +1,109 @@
<?php
namespace Zotlabs\Module;
/**
* @file mod/cloud.php
* @brief Initialize Hubzilla's cloud (SabreDAV).
*
* Module for accessing the DAV storage area.
*/
use Sabre\DAV as SDAV;
use \Zotlabs\Storage;
// composer autoloader for SabreDAV
require_once('vendor/autoload.php');
/**
* @brief Fires up the SabreDAV server.
*
* @param App &$a
*/
class Cloud extends \Zotlabs\Web\Controller {
function init() {
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 = 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();
$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
$server = new SDAV\Server($rootDirectory);
// prevent overwriting changes each other with a lock backend
$lockBackend = new SDAV\Locks\Backend\File('store/[data]/locks');
$lockPlugin = new SDAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);
$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);
$server->addPlugin($browser);
// Experimental QuotaPlugin
// 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();
killme();
}
}

73
Zotlabs/Module/Common.php Normal file
View File

@@ -0,0 +1,73 @@
<?php
namespace Zotlabs\Module;
require_once('include/socgraph.php');
class Common extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && intval(argv(1)))
$channel_id = intval(argv(1));
else {
notice( t('No channel.') . EOL );
\App::$error = 404;
return;
}
$x = q("select channel_address from channel where channel_id = %d limit 1",
intval($channel_id)
);
if($x)
profile_load($a,$x[0]['channel_address'],0);
}
function get() {
$o = '';
if(! \App::$profile['profile_uid'])
return;
$observer_hash = get_observer_hash();
if(! perm_is_allowed(\App::$profile['profile_uid'],$observer_hash,'view_contacts')) {
notice( t('Permission denied.') . EOL);
return;
}
$o .= '<h2>' . t('Common connections') . '</h2>';
$t = count_common_friends(\App::$profile['profile_uid'],$observer_hash);
if(! $t) {
notice( t('No connections in common.') . EOL);
return $o;
}
$r = common_friends(\App::$profile['profile_uid'],$observer_hash);
if($r) {
$tpl = get_markup_template('common_friends.tpl');
foreach($r as $rr) {
$o .= replace_macros($tpl,array(
'$url' => $rr['xchan_url'],
'$name' => $rr['xchan_name'],
'$photo' => $rr['xchan_photo_m'],
'$tags' => ''
));
}
$o .= cleardiv();
}
return $o;
}
}

130
Zotlabs/Module/Connect.php Normal file
View File

@@ -0,0 +1,130 @@
<?php
namespace Zotlabs\Module; /** @file */
require_once('include/Contact.php');
require_once('include/contact_widgets.php');
require_once('include/items.php');
class Connect extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$r = q("select * from channel where channel_address = '%s' limit 1",
dbesc($which)
);
if($r)
\App::$data['channel'] = $r[0];
profile_load($a,$which,'');
}
function post() {
if(! array_key_exists('channel', \App::$data))
return;
$edit = ((local_channel() && (local_channel() == \App::$data['channel']['channel_id'])) ? true : false);
if($edit) {
$has_premium = ((\App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? 1 : 0);
$premium = (($_POST['premium']) ? intval($_POST['premium']) : 0);
$text = escape_tags($_POST['text']);
if($has_premium != $premium) {
$r = q("update channel set channel_pageflags = ( channel_pageflags %s %d ) where channel_id = %d",
db_getfunc('^'),
intval(PAGE_PREMIUM),
intval(local_channel())
);
proc_run('php','include/notifier.php','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
goaway(z_root() . '/' . \App::$query_string);
}
$url = '';
$observer = \App::get_observer();
if(($observer) && ($_POST['submit'] === t('Continue'))) {
if($observer['xchan_follow'])
$url = sprintf($observer['xchan_follow'],urlencode(\App::$data['channel']['channel_address'] . '@' . \App::get_hostname()));
if(! $url) {
$r = q("select * from hubloc where hubloc_hash = '%s' order by hubloc_id desc limit 1",
dbesc($observer['xchan_hash'])
);
if($r)
$url = $r[0]['hubloc_url'] . '/follow?f=&url=' . urlencode(\App::$data['channel']['channel_address'] . '@' . \App::get_hostname());
}
}
if($url)
goaway($url . '&confirm=1');
else
notice('Unable to connect to your home hub location.');
}
function get() {
$edit = ((local_channel() && (local_channel() == \App::$data['channel']['channel_id'])) ? true : false);
$text = get_pconfig(\App::$data['channel']['channel_id'],'system','selltext');
if($edit) {
$o = replace_macros(get_markup_template('sellpage_edit.tpl'),array(
'$header' => t('Premium Channel Setup'),
'$address' => \App::$data['channel']['channel_address'],
'$premium' => array('premium', t('Enable premium channel connection restrictions'),((\App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? '1' : ''),''),
'$lbl_about' => t('Please enter your restrictions or conditions, such as paypal receipt, usage guidelines, etc.'),
'$text' => $text,
'$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'),
'$lbl2' => t('Potential connections will then see the following text before proceeding:'),
'$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'),
'$submit' => t('Submit'),
));
return $o;
}
else {
if(! $text)
$text = t('(No specific instructions have been provided by the channel owner.)');
$submit = replace_macros(get_markup_template('sellpage_submit.tpl'), array(
'$continue' => t('Continue'),
'$address' => \App::$data['channel']['channel_address']
));
$o = replace_macros(get_markup_template('sellpage_view.tpl'),array(
'$header' => t('Restricted or Premium Channel'),
'$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'),
'$text' => prepare_text($text),
'$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'),
'$submit' => $submit,
));
$arr = array('channel' => \App::$data['channel'],'observer' => \App::get_observer(), 'sellpage' => $o, 'submit' => $submit);
call_hooks('connect_premium', $arr);
$o = $arr['sellpage'];
}
return $o;
}
}

View File

@@ -0,0 +1,324 @@
<?php
namespace Zotlabs\Module;
require_once('include/Contact.php');
require_once('include/socgraph.php');
require_once('include/contact_selectors.php');
require_once('include/group.php');
require_once('include/contact_widgets.php');
require_once('include/zot.php');
require_once('include/widgets.php');
class Connections extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
$channel = \App::get_channel();
if($channel)
head_set_icon($channel['xchan_photo_s']);
}
function get() {
$sort_type = 0;
$o = '';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
}
$blocked = false;
$hidden = false;
$ignored = false;
$archived = false;
$unblocked = false;
$pending = false;
$unconnected = false;
$all = false;
if(! $_REQUEST['aj'])
$_SESSION['return_url'] = \App::$query_string;
$search_flags = '';
$head = '';
if(argc() == 2) {
switch(argv(1)) {
case 'blocked':
$search_flags = " and abook_blocked = 1 ";
$head = t('Blocked');
$blocked = true;
break;
case 'ignored':
$search_flags = " and abook_ignored = 1 ";
$head = t('Ignored');
$ignored = true;
break;
case 'hidden':
$search_flags = " and abook_hidden = 1 ";
$head = t('Hidden');
$hidden = true;
break;
case 'archived':
$search_flags = " and abook_archived = 1 ";
$head = t('Archived');
$archived = true;
break;
case 'pending':
$search_flags = " and abook_pending = 1 ";
$head = t('New');
$pending = true;
nav_set_selected('intros');
break;
case 'ifpending':
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
intval(local_channel())
);
if($r && $r[0]['total']) {
$search_flags = " and abook_pending = 1 ";
$head = t('New');
$pending = true;
nav_set_selected('intros');
\App::$argv[1] = 'pending';
}
else {
$head = t('All');
$search_flags = '';
$all = true;
\App::$argc = 1;
unset(\App::$argv[1]);
}
nav_set_selected('intros');
break;
// case 'unconnected':
// $search_flags = " and abook_unconnected = 1 ";
// $head = t('Unconnected');
// $unconnected = true;
// break;
case 'all':
$head = t('All');
default:
$search_flags = '';
$all = true;
break;
}
$sql_extra = $search_flags;
if(argv(1) === 'pending')
$sql_extra .= " and abook_ignored = 0 ";
}
else {
$sql_extra = " and abook_blocked = 0 ";
$unblocked = true;
}
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
$tabs = array(
/*
array(
'label' => t('Suggestions'),
'url' => z_root() . '/suggest',
'sel' => '',
'title' => t('Suggest new connections'),
),
*/
'pending' => array(
'label' => t('New Connections'),
'url' => z_root() . '/connections/pending',
'sel' => ($pending) ? 'active' : '',
'title' => t('Show pending (new) connections'),
),
'all' => array(
'label' => t('All Connections'),
'url' => z_root() . '/connections/all',
'sel' => ($all) ? 'active' : '',
'title' => t('Show all connections'),
),
/*
array(
'label' => t('Unblocked'),
'url' => z_root() . '/connections',
'sel' => (($unblocked) && (! $search) && (! $nets)) ? 'active' : '',
'title' => t('Only show unblocked connections'),
),
*/
'blocked' => array(
'label' => t('Blocked'),
'url' => z_root() . '/connections/blocked',
'sel' => ($blocked) ? 'active' : '',
'title' => t('Only show blocked connections'),
),
'ignored' => array(
'label' => t('Ignored'),
'url' => z_root() . '/connections/ignored',
'sel' => ($ignored) ? 'active' : '',
'title' => t('Only show ignored connections'),
),
'archived' => array(
'label' => t('Archived'),
'url' => z_root() . '/connections/archived',
'sel' => ($archived) ? 'active' : '',
'title' => t('Only show archived connections'),
),
'hidden' => array(
'label' => t('Hidden'),
'url' => z_root() . '/connections/hidden',
'sel' => ($hidden) ? 'active' : '',
'title' => t('Only show hidden connections'),
),
// array(
// 'label' => t('Unconnected'),
// 'url' => z_root() . '/connections/unconnected',
// 'sel' => ($unconnected) ? 'active' : '',
// 'title' => t('Only show one-way connections'),
// ),
);
//$tab_tpl = get_markup_template('common_tabs.tpl');
//$t = replace_macros($tab_tpl, array('$tabs'=>$tabs));
$searching = false;
if($search) {
$search_hdr = $search;
$search_txt = dbesc(protect_sprintf(preg_quote($search)));
$searching = true;
}
$sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : "");
if($_REQUEST['gid']) {
$sql_extra .= " and xchan_hash in ( select xchan from group_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) ";
}
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ",
intval(local_channel())
);
if($r) {
\App::set_pager_total($r[0]['total']);
$total = $r[0]['total'];
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d OFFSET %d ",
intval(local_channel()),
intval(\App::$pager['itemspage']),
intval(\App::$pager['start'])
);
$contacts = array();
if(count($r)) {
foreach($r as $rr) {
if($rr['xchan_url']) {
$status_str = '';
$status = array(
((intval($rr['abook_pending'])) ? t('Pending approval') : ''),
((intval($rr['abook_archived'])) ? t('Archived') : ''),
((intval($rr['abook_hidden'])) ? t('Hidden') : ''),
((intval($rr['abook_ignored'])) ? t('Ignored') : ''),
((intval($rr['abook_blocked'])) ? t('Blocked') : '')
);
foreach($status as $str) {
if(!$str)
continue;
$status_str .= $str;
$status_str .= ', ';
}
$status_str = rtrim($status_str, ', ');
$contacts[] = array(
'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']),
'edit_hover' => t('Edit connection'),
'delete_hover' => t('Delete connection'),
'id' => $rr['abook_id'],
'thumb' => $rr['xchan_photo_m'],
'name' => $rr['xchan_name'],
'classes' => (intval($rr['abook_archived']) ? 'archived' : ''),
'link' => z_root() . '/connedit/' . $rr['abook_id'],
'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop',
'delete' => t('Delete'),
'url' => chanlink_url($rr['xchan_url']),
'webbie_label' => t('Channel address'),
'webbie' => $rr['xchan_addr'],
'network_label' => t('Network'),
'network' => network_to_name($rr['xchan_network']),
'public_forum' => ((intval($rr['xchan_pubforum'])) ? true : false),
'status_label' => t('Status'),
'status' => $status_str,
'connected_label' => t('Connected'),
'connected' => datetime_convert('UTC',date_default_timezone_get(),$rr['abook_created'], 'c'),
'approve_hover' => t('Approve connection'),
'approve' => (($rr['abook_pending']) ? t('Approve') : false),
'ignore_hover' => t('Ignore connection'),
'ignore' => ((! $rr['abook_ignored']) ? t('Ignore') : false),
'recent_label' => t('Recent activity'),
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id'])
);
}
}
}
if($_REQUEST['aj']) {
if($contacts) {
$o = replace_macros(get_markup_template('contactsajax.tpl'),array(
'$contacts' => $contacts,
'$edit' => t('Edit'),
));
}
else {
$o = '<div id="content-complete"></div>';
}
echo $o;
killme();
}
else {
$o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$o .= replace_macros(get_markup_template('connections.tpl'),array(
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
'$tabs' => $tabs,
'$total' => $total,
'$search' => $search_hdr,
'$label' => t('Search'),
'$desc' => t('Search your connections'),
'$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""),
'$submit' => t('Find'),
'$edit' => t('Edit'),
'$cmd' => \App::$cmd,
'$contacts' => $contacts,
'$paginate' => paginate($a),
));
}
if(! $contacts)
$o .= '<div id="content-complete"></div>';
return $o;
}
}

763
Zotlabs/Module/Connedit.php Normal file
View File

@@ -0,0 +1,763 @@
<?php
namespace Zotlabs\Module;
/* @file connedit.php
* @brief In this file the connection-editor form is generated and evaluated.
*
*
*/
require_once('include/Contact.php');
require_once('include/socgraph.php');
require_once('include/contact_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 {
function init() {
if(! local_channel())
return;
if((argc() >= 2) && intval(argv(1))) {
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
intval(local_channel()),
intval(argv(1))
);
if($r) {
\App::$poi = $r[0];
}
}
$channel = \App::get_channel();
if($channel)
head_set_icon($channel['xchan_photo_s']);
}
/* @brief Evaluate posted values and set changes
*
*/
function post() {
if(! local_channel())
return;
$contact_id = intval(argv(1));
if(! $contact_id)
return;
$channel = \App::get_channel();
// TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the
// connection enable is toggled to a special autopost url and set permissions immediately, leaving
// the other form elements alone pending a manual submit of the form. The downside is that there
// will be a window of opportunity when the permissions have been set but before you've had a chance
// to review and possibly restrict them. The upside is we won't have to warn you that your connection
// can't do anything until you save the bloody form.
$autopost = (((argc() > 2) && (argv(2) === 'auto')) ? true : false);
$orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
intval($contact_id),
intval(local_channel())
);
if(! $orig_record) {
notice( t('Could not access contact record.') . EOL);
goaway(z_root() . '/connections');
return; // NOTREACHED
}
call_hooks('contact_edit_post', $_POST);
if(intval($orig_record[0]['abook_self'])) {
$autoperms = intval($_POST['autoperms']);
$is_self = true;
}
else {
$autoperms = null;
$is_self = false;
}
$profile_id = $_POST['profile_assign'];
if($profile_id) {
$r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND `uid` = %d LIMIT 1",
dbesc($profile_id),
intval(local_channel())
);
if(! count($r)) {
notice( t('Could not locate selected profile.') . EOL);
return;
}
}
$abook_incl = escape_tags($_POST['abook_incl']);
$abook_excl = escape_tags($_POST['abook_excl']);
$hidden = intval($_POST['hidden']);
$priority = intval($_POST['poll']);
if($priority > 5 || $priority < 0)
$priority = 0;
$closeness = intval($_POST['closeness']);
if($closeness < 0)
$closeness = 99;
$rating = intval($_POST['rating']);
if($rating < (-10))
$rating = (-10);
if($rating > 10)
$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;
}
}
$new_friend = false;
if(! $is_self) {
$signed = $orig_record[0]['abook_xchan'] . '.' . $rating . '.' . $rating_text;
$sig = base64url_encode(rsa_sign($signed,$channel['channel_prvkey']));
$z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
dbesc($channel['channel_hash']),
dbesc($orig_record[0]['abook_xchan'])
);
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)
);
}
else {
$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']),
intval($rating),
dbesc($rating_text),
dbesc($sig),
dbesc(datetime_convert())
);
$z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
dbesc($channel['channel_hash']),
dbesc($orig_record[0]['abook_xchan'])
);
if($z)
$record = $z[0]['xlink_id'];
}
if($record) {
proc_run('php','include/ratenotif.php','rating',$record);
}
}
if(($_REQUEST['pending']) && intval($orig_record[0]['abook_pending'])) {
$new_friend = true;
// @fixme it won't be common, but when you accept a new connection request
// the permissions will now be that of your permissions role and ignore
// any you may have set manually on the form. We'll probably see a bug if somebody
// tries to set the permissions *and* approve the connection in the same
// request. The workaround is to approve the connection, then go back and
// adjust permissions as desired.
$abook_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'])
$abook_my_perms = $x['perms_accept'];
}
}
$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,
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),
dbesc($abook_excl),
intval($contact_id),
intval(local_channel())
);
if($orig_record[0]['abook_profile'] != $profile_id) {
//Update profile photo permissions
logger('A new profile was assigned - updating profile photos');
profile_photo_set_profile_perms($profile_id);
}
if($r)
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($new_friend) {
$default_group = $channel['channel_default_group'];
if($default_group) {
require_once('include/group.php');
$g = group_rec_byhash(local_channel(),$default_group);
if($g)
group_add_member(local_channel(),'',\App::$poi['abook_xchan'],$g['id']);
}
// Check if settings permit ("post new friend activity" is allowed, and
// friends in general or this friend in particular aren't hidden)
// and send out a new friend activity
$pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0",
intval($channel['channel_id'])
);
if(($pr) && (! intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'],'system','post_newfriend')))) {
$xarr = array();
$xarr['verb'] = ACTIVITY_FRIEND;
$xarr['item_wall'] = 1;
$xarr['item_origin'] = 1;
$xarr['item_thread_top'] = 1;
$xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
$xarr['allow_cid'] = $channel['channel_allow_cid'];
$xarr['allow_gid'] = $channel['channel_allow_gid'];
$xarr['deny_cid'] = $channel['channel_deny_cid'];
$xarr['deny_gid'] = $channel['channel_deny_gid'];
$xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0);
$obj = array(
'type' => ACTIVITY_OBJ_PERSON,
'title' => \App::$poi['xchan_name'],
'id' => \App::$poi['xchan_hash'],
'link' => array(
array('rel' => 'alternate', 'type' => 'text/html', 'href' => \App::$poi['xchan_url']),
array('rel' => 'photo', 'type' => \App::$poi['xchan_photo_mimetype'], 'href' => \App::$poi['xchan_photo_l'])
),
);
$xarr['object'] = 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]';
$xarr['body'] .= "\n\n\n" . '[zrl=' . \App::$poi['xchan_url'] . '][zmg=80x80]' . \App::$poi['xchan_photo_m'] . '[/zmg][/zrl]';
post_activity_item($xarr);
}
// pull in a bit of content if there is any to pull in
proc_run('php','include/onepoll.php',$contact_id);
}
// Refresh the structure in memory with the new data
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
intval(local_channel()),
intval($contact_id)
);
if($r) {
\App::$poi = $r[0];
}
if($new_friend) {
$arr = array('channel_id' => local_channel(), 'abook' => \App::$poi);
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']))
goaway(z_root() . '/connections/ifpending');
return;
}
/* @brief Clone connection
*
*
*/
function connedit_clone(&$a) {
if(! \App::$poi)
return;
$channel = \App::get_channel();
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
intval(local_channel()),
intval(\App::$poi['abook_id'])
);
if($r) {
\App::$poi = $r[0];
}
$clone = \App::$poi;
unset($clone['abook_id']);
unset($clone['abook_account']);
unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_hash'],$clone['abook_xchan']);
if($abconfig)
$clone['abconfig'] = $abconfig;
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
}
/* @brief Generate content of connection edit page
*
*
*/
function get() {
$sort_type = 0;
$o = '';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
}
$channel = \App::get_channel();
$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'];
}
$yes_no = array(t('No'),t('Yes'));
if($my_perms) {
$o .= "<script>function connectDefaultShare() {
\$('.abook-edit-me').each(function() {
if(! $(this).is(':disabled'))
$(this).prop('checked', false);
});\n\n";
$perms = get_perms();
foreach($perms as $p => $v) {
if($my_perms & $v[1]) {
$o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n";
}
}
$o .= " }\n</script>\n";
}
if(argc() == 3) {
$contact_id = intval(argv(1));
if(! $contact_id)
return;
$cmd = argv(2);
$orig_record = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1",
intval($contact_id),
intval(local_channel())
);
if(! count($orig_record)) {
notice( t('Could not access address book record.') . EOL);
goaway(z_root() . '/connections');
}
if($cmd === 'update') {
// pull feed and consume it, which should subscribe to the hub.
proc_run('php',"include/poller.php","$contact_id");
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'refresh') {
if($orig_record[0]['xchan_network'] === 'zot') {
if(! zot_refresh($orig_record[0],\App::get_channel()))
notice( t('Refresh failed - channel is currently unavailable.') );
}
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);
}
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'block') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_BLOCKED)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'ignore') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_IGNORED)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'archive') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_ARCHIVED)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'hide') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_HIDDEN)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
// We'll prevent somebody from unapproving an already approved contact.
// Though maybe somebody will want this eventually (??)
if($cmd === 'approve') {
if(intval($orig_record[0]['abook_pending'])) {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_PENDING)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
}
goaway(z_root() . '/connedit/' . $contact_id);
}
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).
// The issue is that the abook DB record _may_ get destroyed when we call contact_remove. As the notifier runs
// in the background there could be a race condition preventing this packet from being sent in all cases.
// PLACEHOLDER
contact_remove(local_channel(), $orig_record[0]['abook_id']);
build_sync_packet(0 /* use the current local_channel */,
array('abook' => array(array(
'abook_xchan' => $orig_record[0]['abook_xchan'],
'entry_deleted' => true))
)
);
info( t('Connection has been removed.') . EOL );
if(x($_SESSION,'return_url'))
goaway(z_root() . '/' . $_SESSION['return_url']);
goaway(z_root() . '/contacts');
}
}
if(\App::$poi) {
$contact_id = \App::$poi['abook_id'];
$contact = \App::$poi;
$tools = array(
'view' => array(
'label' => t('View Profile'),
'url' => chanlink_cid($contact['abook_id']),
'sel' => '',
'title' => sprintf( t('View %s\'s profile'), $contact['xchan_name']),
),
'refresh' => array(
'label' => t('Refresh Permissions'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/refresh',
'sel' => '',
'title' => t('Fetch updated permissions'),
),
'recent' => array(
'label' => t('Recent Activity'),
'url' => z_root() . '/network/?f=&cid=' . $contact['abook_id'],
'sel' => '',
'title' => t('View recent posts and comments'),
),
'block' => array(
'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/block',
'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
'title' => t('Block (or Unblock) all communications with this connection'),
'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
),
'ignore' => array(
'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/ignore',
'sel' => (intval($contact['abook_ignored']) ? 'active' : ''),
'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
),
'archive' => array(
'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive',
'sel' => (intval($contact['abook_archived']) ? 'active' : ''),
'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
),
'hide' => array(
'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/hide',
'sel' => (intval($contact['abook_hidden']) ? 'active' : ''),
'title' => t('Hide or Unhide this connection from your other connections'),
'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
),
'delete' => array(
'label' => t('Delete'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/drop',
'sel' => '',
'title' => t('Delete this connection'),
),
);
$self = false;
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')) {
$labels = array(
t('Me'),
t('Family'),
t('Friends'),
t('Acquaintances'),
t('All')
);
call_hooks('affinity_labels',$labels);
$label_str = '';
if($labels) {
foreach($labels as $l) {
if($label_str) {
$label_str .= ", '|'";
$label_str .= ", '" . $l . "'";
}
else
$label_str .= "'" . $l . "'";
}
}
$slider_tpl = get_markup_template('contact_slider.tpl');
$slide = replace_macros($slider_tpl,array(
'$min' => 1,
'$val' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 99),
'$labels' => $label_str,
));
}
$rating_val = 0;
$rating_text = '';
$xl = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
dbesc($channel['channel_hash']),
dbesc($contact['xchan_hash'])
);
if($xl) {
$rating_val = intval($xl[0]['xlink_rating']);
$rating_text = $xl[0]['xlink_rating_text'];
}
$poco_rating = get_config('system','poco_rating_enable');
// if unset default to enabled
if($poco_rating === false)
$poco_rating = true;
if($poco_rating) {
$rating = replace_macros(get_markup_template('rating_slider.tpl'),array(
'$min' => -10,
'$val' => $rating_val
));
}
else {
$rating = false;
}
$perms = array();
$channel = \App::get_channel();
$global_perms = get_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')));
$multiprofs = ((feature_enabled(local_channel(),'multi_profiles')) ? true : false);
if($slide && !$multiprofs)
$affinity = t('Set Affinity');
if(!$slide && $multiprofs)
$affinity = t('Set Profile');
if($slide && $multiprofs)
$affinity = t('Set Affinity & Profile');
foreach($global_perms as $k => $v) {
$thisperm = (($contact['abook_my_perms'] & $v[1]) ? "1" : '');
$checkinherited = ((($channel[$v[0]]) && ($channel[$v[0]] != PERMS_SPECIFIC)) ? "1" : '');
// 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);
}
$locstr = '';
$locs = q("select hubloc_addr as location from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s'
and hubloc_deleted = 0 and site_dead = 0",
dbesc($contact['xchan_hash'])
);
if($locs) {
foreach($locs as $l) {
if(!($l['location']))
continue;
if(strpos($locstr,$l['location']) !== false)
continue;
if(strlen($locstr))
$locstr .= ', ';
$locstr .= $l['location'];
}
}
else
$locstr = t('none');
$o .= replace_macros($tpl,array(
'$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name'])),
'$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no),
'$addr' => $contact['xchan_addr'],
'$addr_text' => t('This connection\'s primary address is'),
'$loc_text' => t('Available locations:'),
'$locstr' => $locstr,
'$notself' => (($self) ? '' : '1'),
'$self' => (($self) ? '1' : ''),
'$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
'$tools_label' => t('Connection Tools'),
'$tools' => (($self) ? '' : $tools),
'$lbl_slider' => t('Slide to adjust your degree of friendship'),
'$lbl_rating' => t('Rating'),
'$lbl_rating_label' => t('Slide to adjust your rating'),
'$lbl_rating_txt' => t('Optionally explain your rating'),
'$connfilter' => feature_enabled(local_channel(),'connfilter'),
'$connfilter_label' => t('Custom Filter'),
'$incl' => array('abook_incl',t('Only import posts with this text'), $contact['abook_incl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
'$excl' => array('abook_excl',t('Do not import posts with this text'), $contact['abook_excl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
'$rating_text' => array('rating_text', t('Optionally explain your rating'),$rating_text,''),
'$rating_info' => t('This information is public!'),
'$rating' => $rating,
'$rating_val' => $rating_val,
'$slide' => $slide,
'$affinity' => $affinity,
'$pending_label' => t('Connection Pending Approval'),
'$is_pending' => (intval($contact['abook_pending']) ? 1 : ''),
'$unapproved' => $unapproved,
'$inherited' => t('inherited'),
'$submit' => t('Submit'),
'$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
'$close' => $contact['abook_closeness'],
'$them' => t('Their Settings'),
'$me' => t('My Settings'),
'$perms' => $perms,
'$permlbl' => t('Individual Permissions'),
'$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
'$permnote_self' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can change those settings here but they wont have any impact unless the inherited setting changes.'),
'$lastupdtext' => t('Last update:'),
'$last_update' => relative_date($contact['abook_connected']),
'$profile_select' => contact_profile_assign($contact['abook_profile']),
'$multiprofs' => $multiprofs,
'$contact_id' => $contact['abook_id'],
'$name' => $contact['xchan_name'],
));
$arr = array('contact' => $contact,'output' => $o);
call_hooks('contact_edit', $arr);
return $arr['output'];
}
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace Zotlabs\Module;
require_once('include/group.php');
class Contactgroup extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
killme();
}
if((argc() > 2) && (intval(argv(1))) && (argv(2))) {
$r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
dbesc(base64url_decode(argv(2))),
intval(local_channel())
);
if($r)
$change = $r[0]['abook_xchan'];
}
if((argc() > 1) && (intval(argv(1)))) {
$r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if(! $r) {
killme();
}
$group = $r[0];
$members = group_get_members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
$preselected[] = $member['xchan_hash'];
}
if($change) {
if(in_array($change,$preselected)) {
group_rmv_member(local_channel(),$group['name'],$change);
}
else {
group_add_member(local_channel(),$group['name'],$change);
}
}
}
killme();
}
}

View File

@@ -0,0 +1,423 @@
<?php
namespace Zotlabs\Module;
/*
@file cover_photo.php
@brief Module-file with functions for handling of cover-photos
*/
require_once('include/photo/photo_driver.php');
require_once('include/identity.php');
/* @brief Initalize the cover-photo edit view
*
* @param $a Current application
* @return void
*
*/
class Cover_photo extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel()) {
return;
}
$channel = \App::get_channel();
profile_load($a,$channel['channel_address']);
}
/* @brief Evaluate posted values
*
* @param $a Current application
* @return void
*
*/
function post() {
if(! local_channel()) {
return;
}
$channel = \App::get_channel();
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
if((x($_POST,'cropfinal')) && ($_POST['cropfinal'] == 1)) {
// phase 2 - we have finished cropping
if(argc() != 2) {
notice( t('Image uploaded but image cropping failed.') . EOL );
return;
}
$image_id = argv(1);
if(substr($image_id,-2,1) == '-') {
$scale = substr($image_id,-1,1);
$image_id = substr($image_id,0,-2);
}
$srcX = $_POST['xstart'];
$srcY = $_POST['ystart'];
$srcW = $_POST['xfinal'] - $srcX;
$srcH = $_POST['yfinal'] - $srcY;
$r = q("select gender from profile where uid = %d and is_default = 1 limit 1",
intval(local_channel())
);
if($r) {
$profile = $r[0];
}
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND scale = 0 LIMIT 1",
dbesc($image_id),
intval(local_channel())
);
if($r) {
$base_image = $r[0];
$base_image['data'] = (($r[0]['os_storage']) ? @file_get_contents($base_image['data']) : dbunescbin($base_image['data']));
$im = photo_factory($base_image['data'], $base_image['type']);
if($im->is_valid()) {
// We are scaling and cropping the relative pixel locations to the original photo instead of the
// scaled photo we operated on.
// 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",
dbesc($image_id),
intval(local_channel())
);
$scaled_width = $g[0]['width'];
$scaled_height = $g[0]['height'];
if((! $scaled_width) || (! $scaled_height)) {
logger('potential divide by zero scaling cover photo');
return;
}
// unset all other cover photos
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
intval(PHOTO_NORMAL),
intval(PHOTO_COVER),
intval(local_channel())
);
$orig_srcx = ( $r[0]['width'] / $scaled_width ) * $srcX;
$orig_srcy = ( $r[0]['height'] / $scaled_height ) * $srcY;
$orig_srcw = ( $srcW / $scaled_width ) * $r[0]['width'];
$orig_srch = ( $srcH / $scaled_height ) * $r[0]['height'];
$im->cropImageRect(1200,435,$orig_srcx, $orig_srcy, $orig_srcw, $orig_srch);
$aid = get_account_id();
$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['photo_usage'] = PHOTO_COVER;
$r1 = $im->save($p);
$im->doScaleImage(850,310);
$p['scale'] = 8;
$r2 = $im->save($p);
$im->doScaleImage(425,160);
$p['scale'] = 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 ",
dbesc($base_image['resource_id']),
local_channel()
);
return;
}
$channel = \App::get_channel();
$this->send_cover_photo_activity($channel,$base_image,$profile);
}
else
notice( t('Unable to process image') . EOL);
}
goaway(z_root() . '/channel/' . $channel['channel_address']);
}
$hash = photo_new_resource();
$smallest = 0;
require_once('include/attach.php');
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash));
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",
dbesc($hash),
intval(local_channel())
);
if(! $i) {
notice( t('Image upload failed.') . EOL );
return;
}
$os_storage = false;
foreach($i as $ii) {
$smallest = intval($ii['scale']);
$os_storage = intval($ii['os_storage']);
$imagedata = $ii['data'];
$filetype = $ii['type'];
}
}
$imagedata = (($os_storage) ? @file_get_contents($imagedata) : $imagedata);
$ph = photo_factory($imagedata, $filetype);
if(! $ph->is_valid()) {
notice( t('Unable to process image.') . EOL );
return;
}
return $this->cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
}
function send_cover_photo_activity($channel,$photo,$profile) {
$arr = array();
$arr['item_thread_top'] = 1;
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
$arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
$arr['verb'] = ACTIVITY_UPDATE;
$arr['object'] = 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')
));
if($profile && stripos($profile['gender'],t('female')) !== false)
$t = t('%1$s updated her %2$s');
elseif($profile && stripos($profile['gender'],t('male')) !== false)
$t = t('%1$s updated his %2$s');
else
$t = t('%1$s updated their %2$s');
$ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]';
$ltext = '[zrl=' . z_root() . '/profile/' . $channel['channel_address'] . ']' . '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-8[/zmg][/zrl]';
$arr['body'] = sprintf($t,$channel['channel_name'],$ptext) . "\n\n" . $ltext;
$acl = new \Zotlabs\Access\AccessList($channel);
$x = $acl->get();
$arr['allow_cid'] = $x['allow_cid'];
$arr['allow_gid'] = $x['allow_gid'];
$arr['deny_cid'] = $x['deny_cid'];
$arr['deny_gid'] = $x['deny_gid'];
$arr['uid'] = $channel['channel_id'];
$arr['aid'] = $channel['channel_account_id'];
$arr['owner_xchan'] = $channel['channel_hash'];
$arr['author_xchan'] = $channel['channel_hash'];
post_activity_item($arr);
}
/* @brief Generate content of profile-photo view
*
* @param $a Current application
* @return void
*
*/
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL );
return;
}
$channel = \App::get_channel();
$newuser = false;
if(argc() == 2 && argv(1) === 'new')
$newuser = true;
if(argv(1) === 'use') {
if (argc() < 3) {
notice( t('Permission denied.') . EOL );
return;
};
// check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
$resource_id = argv(2);
$r = q("SELECT id, album, scale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY scale ASC",
intval(local_channel()),
dbesc($resource_id)
);
if(! $r) {
notice( t('Photo not available.') . EOL );
return;
}
$havescale = false;
foreach($r as $rr) {
if($rr['scale'] == 7)
$havescale = true;
}
$r = q("SELECT `data`, `type`, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
intval($r[0]['id']),
intval(local_channel())
);
if(! $r) {
notice( t('Photo not available.') . EOL );
return;
}
if(intval($r[0]['os_storage']))
$data = @file_get_contents($r[0]['data']);
else
$data = dbunescbin($r[0]['data']);
$ph = photo_factory($data, $r[0]['type']);
$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",
dbesc($r[0]['resource_id']),
intval(local_channel())
);
if($i) {
$hash = $i[0]['resource_id'];
foreach($i as $ii) {
$smallest = intval($ii['scale']);
}
}
}
cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
}
if(! x(\App::$data,'imagecrop')) {
$tpl = get_markup_template('cover_photo.tpl');
$o .= replace_macros($tpl,array(
'$user' => \App::$channel['channel_address'],
'$lbl_upfile' => t('Upload File:'),
'$lbl_profiles' => t('Select a profile:'),
'$title' => t('Upload Cover Photo'),
'$submit' => t('Upload'),
'$profiles' => $profiles,
'$form_security_token' => get_form_security_token("cover_photo"),
// FIXME - yuk
'$select' => sprintf('%s %s', t('or'), ($newuser) ? '<a href="' . z_root() . '">' . t('skip this step') . '</a>' : '<a href="'. z_root() . '/photos/' . \App::$channel['channel_address'] . '">' . t('select a photo from your photo albums') . '</a>')
));
call_hooks('cover_photo_content_end', $o);
return $o;
}
else {
$filename = \App::$data['imagecrop'] . '-3';
$resolution = 3;
$tpl = get_markup_template("cropcover.tpl");
$o .= replace_macros($tpl,array(
'$filename' => $filename,
'$profile' => intval($_REQUEST['profile']),
'$resource' => \App::$data['imagecrop'] . '-3',
'$image_url' => z_root() . '/photo/' . $filename,
'$title' => t('Crop Image'),
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
'$form_security_token' => get_form_security_token("cover_photo"),
'$done' => t('Done Editing')
));
return $o;
}
return; // NOTREACHED
}
/* @brief Generate the UI for photo-cropping
*
* @param $a Current application
* @param $ph Photo-Factory
* @return void
*
*/
function cover_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
$max_length = get_config('system','max_image_length');
if(! $max_length)
$max_length = MAX_IMAGE_LENGTH;
if($max_length > 0)
$ph->scaleImage($max_length);
$width = $ph->getWidth();
$height = $ph->getHeight();
if($width < 300 || $height < 300) {
$ph->scaleImageUp(240);
$width = $ph->getWidth();
$height = $ph->getHeight();
}
\App::$data['imagecrop'] = $hash;
\App::$data['imagecrop_resolution'] = $smallest;
\App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array());
return;
}
}

165
Zotlabs/Module/Dav.php Normal file
View File

@@ -0,0 +1,165 @@
<?php
namespace Zotlabs\Module;
/**
* @file mod/dav.php
* @brief Initialize Hubzilla's cloud (SabreDAV).
*
* Module for accessing the DAV storage area from a DAV client.
*/
use \Sabre\DAV as SDAV;
use \Zotlabs\Storage;
// composer autoloader for SabreDAV
require_once('vendor/autoload.php');
/**
* @brief Fires up the SabreDAV server.
*
* @param App &$a
*/
class Dav extends \Zotlabs\Web\Controller {
function init() {
// workaround for HTTP-auth in CGI mode
if (x($_SERVER, 'REDIRECT_REMOTE_USER')) {
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ;
if(strlen($userpass)) {
list($name, $password) = explode(':', $userpass);
$_SERVER['PHP_AUTH_USER'] = $name;
$_SERVER['PHP_AUTH_PW'] = $password;
}
}
if (x($_SERVER, 'HTTP_AUTHORIZATION')) {
$userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ;
if(strlen($userpass)) {
list($name, $password) = explode(':', $userpass);
$_SERVER['PHP_AUTH_USER'] = $name;
$_SERVER['PHP_AUTH_PW'] = $password;
}
}
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 = 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();
// $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
$server = new SDAV\Server($rootDirectory);
$authPlugin = new \Sabre\DAV\Auth\Plugin($auth);
$server->addPlugin($authPlugin);
// prevent overwriting changes each other with a lock backend
$lockBackend = new SDAV\Locks\Backend\File('store/[data]/locks');
$lockPlugin = new SDAV\Locks\Plugin($lockBackend);
$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));
// All we need to do now, is to fire up the server
$server->exec();
killme();
}
}

View File

@@ -0,0 +1,425 @@
<?php
namespace Zotlabs\Module;
require_once('include/socgraph.php');
require_once('include/dir_fns.php');
require_once('include/widgets.php');
require_once('include/bbcode.php');
class Directory extends \Zotlabs\Web\Controller {
function init() {
\App::set_pager_itemspage(60);
if(x($_GET,'ignore')) {
q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
intval(local_channel()),
dbesc($_GET['ignore'])
);
goaway(z_root() . '/directory?suggest=1');
}
$observer = get_observer_hash();
$global_changed = false;
$safe_changed = false;
$pubforums_changed = false;
if(array_key_exists('global',$_REQUEST)) {
$globaldir = intval($_REQUEST['global']);
$global_changed = true;
}
if($global_changed) {
$_SESSION['globaldir'] = $globaldir;
if($observer)
set_xconfig($observer,'directory','globaldir',$globaldir);
}
if(array_key_exists('safe',$_REQUEST)) {
$safemode = intval($_REQUEST['safe']);
$safe_changed = true;
}
if($safe_changed) {
$_SESSION['safemode'] = $safemode;
if($observer)
set_xconfig($observer,'directory','safemode',$safemode);
}
if(array_key_exists('pubforums',$_REQUEST)) {
$pubforums = intval($_REQUEST['pubforums']);
$pubforums_changed = true;
}
if($pubforums_changed) {
$_SESSION['pubforums'] = $pubforums;
if($observer)
set_xconfig($observer,'directory','pubforums',$pubforums);
}
}
function get() {
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
notice( t('Public access denied.') . EOL);
return;
}
$observer = get_observer_hash();
$globaldir = get_directory_setting($observer, 'globaldir');
// override your personal global search pref if we're doing a navbar search of the directory
if(intval($_REQUEST['navsearch']))
$globaldir = 1;
$safe_mode = get_directory_setting($observer, 'safemode');
$pubforums = get_directory_setting($observer, 'pubforums');
$o = '';
nav_set_selected('directory');
if(x($_POST,'search'))
$search = notags(trim($_POST['search']));
else
$search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
if(strpos($search,'=') && local_channel() && get_pconfig(local_channel(),'feature','expert'))
$advanced = $search;
$keywords = (($_GET['keywords']) ? $_GET['keywords'] : '');
// Suggest channels if no search terms or keywords are given
$suggest = (local_channel() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : '';
if($suggest) {
$r = suggestion_query(local_channel(),get_observer_hash());
// Remember in which order the suggestions were
$addresses = array();
$common = array();
$index = 0;
foreach($r as $rr) {
$common[$rr['xchan_addr']] = $rr['total'];
$addresses[$rr['xchan_addr']] = $index++;
}
// Build query to get info about suggested people
$advanced = '';
foreach(array_keys($addresses) as $address) {
$advanced .= "address=\"$address\" ";
}
// Remove last space in the advanced query
$advanced = rtrim($advanced);
}
$tpl = get_markup_template('directory_header.tpl');
$dirmode = intval(get_config('system','directory_mode'));
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
$url = z_root() . '/dirsearch';
}
if(! $url) {
$directory = find_upstream_directory($dirmode);
if((! $directory) || (! array_key_exists('url',$directory)) || (! $directory['url']))
logger('CRITICAL: No directory server URL');
$url = $directory['url'] . '/dirsearch';
}
$token = get_config('system','realm_token');
logger('mod_directory: URL = ' . $url, LOGGER_DEBUG);
$contacts = array();
if(local_channel()) {
$x = q("select abook_xchan from abook where abook_channel = %d",
intval(local_channel())
);
if($x) {
foreach($x as $xx)
$contacts[] = $xx['abook_xchan'];
}
}
if($url) {
$numtags = get_config('system','directorytags');
$kw = ((intval($numtags) > 0) ? intval($numtags) : 50);
if(get_config('system','disable_directory_keywords'))
$kw = 0;
$query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : '');
if($token)
$query .= '&t=' . $token;
if(! $globaldir)
$query .= '&hub=' . \App::get_hostname();
if($search)
$query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search);
if(strpos($search,'@'))
$query .= '&address=' . urlencode($search);
if($keywords)
$query .= '&keywords=' . urlencode($keywords);
if($advanced)
$query .= '&query=' . urlencode($advanced);
if(! is_null($pubforums))
$query .= '&pubforums=' . intval($pubforums);
$directory_sort_order = get_config('system','directory_sort_order');
if(! $directory_sort_order)
$directory_sort_order = 'date';
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : $directory_sort_order);
if($sort_order)
$query .= '&order=' . urlencode($sort_order);
if(\App::$pager['page'] != 1)
$query .= '&p=' . \App::$pager['page'];
logger('mod_directory: query: ' . $query);
$x = z_fetch_url($query);
logger('directory: return from upstream: ' . print_r($x,true), LOGGER_DATA);
if($x['success']) {
$t = 0;
$j = json_decode($x['body'],true);
if($j) {
if($j['results']) {
$entries = array();
$photo = 'thumb';
foreach($j['results'] as $rr) {
$profile_link = chanlink_url($rr['url']);
$pdesc = (($rr['description']) ? $rr['description'] . '<br />' : '');
$connect_link = ((local_channel()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : '');
// Checking status is disabled ATM until someone checks the performance impact more carefully
//$online = remote_online_status($rr['address']);
$online = '';
if(in_array($rr['hash'],$contacts))
$connect_link = '';
$location = '';
if(strlen($rr['locale']))
$location .= $rr['locale'];
if(strlen($rr['region'])) {
if(strlen($rr['locale']))
$location .= ', ';
$location .= $rr['region'];
}
if(strlen($rr['country'])) {
if(strlen($location))
$location .= ', ';
$location .= $rr['country'];
}
$age = '';
if(strlen($rr['birthday'])) {
if(($years = age($rr['birthday'],'UTC','')) != 0)
$age = $years;
}
$page_type = '';
if($rr['total_ratings'])
$total_ratings = sprintf( tt("%d rating", "%d ratings", $rr['total_ratings']), $rr['total_ratings']);
else
$total_ratings = '';
$profile = $rr;
if ((x($profile,'locale') == 1)
|| (x($profile,'region') == 1)
|| (x($profile,'postcode') == 1)
|| (x($profile,'country') == 1))
$gender = ((x($profile,'gender') == 1) ? t('Gender: ') . $profile['gender']: False);
$marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False);
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False);
$homepageurl = ((x($profile,'homepage') == 1) ? $profile['homepage'] : '');
$hometown = ((x($profile,'hometown') == 1) ? $profile['hometown'] : False);
$about = ((x($profile,'about') == 1) ? bbcode($profile['about']) : False);
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
$out = '';
if($keywords) {
$keywords = str_replace(',',' ', $keywords);
$keywords = str_replace(' ',' ', $keywords);
$karr = explode(' ', $keywords);
if($karr) {
if(local_channel()) {
$r = q("select keywords from profile where uid = %d and is_default = 1 limit 1",
intval(local_channel())
);
if($r) {
$keywords = str_replace(',',' ', $r[0]['keywords']);
$keywords = str_replace(' ',' ', $keywords);
$marr = explode(' ', $keywords);
}
}
foreach($karr as $k) {
if(strlen($out))
$out .= ', ';
if($marr && in_arrayi($k,$marr))
$out .= '<strong>' . $k . '</strong>';
else
$out .= $k;
}
}
}
$entry = array(
'id' => ++$t,
'profile_link' => $profile_link,
'public_forum' => $rr['public_forum'],
'photo' => $rr['photo'],
'hash' => $rr['hash'],
'alttext' => $rr['name'] . ((local_channel() || remote_channel()) ? ' ' . $rr['address'] : ''),
'name' => $rr['name'],
'age' => $age,
'age_label' => t('Age:'),
'profile' => $profile,
'address' => $rr['address'],
'nickname' => substr($rr['address'],0,strpos($rr['address'],'@')),
'location' => $location,
'location_label' => t('Location:'),
'gender' => $gender,
'total_ratings' => $total_ratings,
'viewrate' => true,
'canrate' => ((local_channel()) ? true : false),
'pdesc' => $pdesc,
'pdesc_label' => t('Description:'),
'marital' => $marital,
'homepage' => $homepage,
'homepageurl' => linkify($homepageurl),
'hometown' => $hometown,
'hometown_label' => t('Hometown:'),
'about' => $about,
'about_label' => t('About:'),
'conn_label' => t('Connect'),
'forum_label' => t('Public Forum:'),
'connect' => $connect_link,
'online' => $online,
'kw' => (($out) ? t('Keywords: ') : ''),
'keywords' => $out,
'ignlink' => $suggest ? z_root() . '/directory?ignore=' . $rr['hash'] : '',
'ignore_label' => t('Don\'t suggest'),
'common_friends' => (($common[$rr['address']]) ? intval($common[$rr['address']]) : ''),
'common_label' => t('Common connections:'),
'common_count' => intval($common[$rr['address']]),
'safe' => $safe_mode
);
$arr = array('contact' => $rr, 'entry' => $entry);
call_hooks('directory_item', $arr);
unset($profile);
unset($location);
if(! $arr['entry']) {
continue;
}
if($sort_order == '' && $suggest) {
$entries[$addresses[$rr['address']]] = $arr['entry']; // Use the same indexes as originally to get the best suggestion first
}
else {
$entries[] = $arr['entry'];
}
}
ksort($entries); // Sort array by key so that foreach-constructs work as expected
if($j['keywords']) {
\App::$data['directory_keywords'] = $j['keywords'];
}
logger('mod_directory: entries: ' . print_r($entries,true), LOGGER_DATA);
if($_REQUEST['aj']) {
if($entries) {
$o = replace_macros(get_markup_template('directajax.tpl'),array(
'$entries' => $entries
));
}
else {
$o = '<div id="content-complete"></div>';
}
echo $o;
killme();
}
else {
$maxheight = 94;
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
$o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
$o .= replace_macros($tpl, array(
'$search' => $search,
'$desc' => t('Find'),
'$finddsc' => t('Finding:'),
'$safetxt' => htmlspecialchars($search,ENT_QUOTES,'UTF-8'),
'$entries' => $entries,
'$dirlbl' => $suggest ? t('Channel Suggestions') : $dirtitle,
'$submit' => t('Find'),
'$next' => alt_pager($a,$j['records'], t('next page'), t('previous page')),
'$sort' => t('Sort options'),
'$normal' => t('Alphabetic'),
'$reverse' => t('Reverse Alphabetic'),
'$date' => t('Newest to Oldest'),
'$reversedate' => t('Oldest to Newest'),
'$suggest' => $suggest ? '&suggest=1' : ''
));
}
}
else {
if($_REQUEST['aj']) {
$o = '<div id="content-complete"></div>';
echo $o;
killme();
}
if(\App::$pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) {
goaway(z_root() . '/chanview/?f=&address=' . $search);
}
info( t("No entries (some entries may be hidden).") . EOL);
}
}
}
}
return $o;
}
}

View File

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

346
Zotlabs/Module/Display.php Normal file
View File

@@ -0,0 +1,346 @@
<?php
namespace Zotlabs\Module;
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())) {
notice( t('Public access denied.') . EOL);
return;
}
require_once("include/bbcode.php");
require_once('include/security.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/items.php');
\App::$page['htmlhead'] .= replace_macros(get_markup_template('display-head.tpl'), array());
if(argc() > 1 && argv(1) !== 'load')
$item_hash = argv(1);
if($_REQUEST['mid'])
$item_hash = $_REQUEST['mid'];
if(! $item_hash) {
\App::$error = 404;
notice( t('Item not found.') . EOL);
return;
}
$observer_is_owner = false;
if(local_channel() && (! $update)) {
$channel = \App::get_channel();
$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']
);
$x = array(
'is_owner' => true,
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
'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),
'bang' => '',
'visitor' => true,
'profile_uid' => local_channel(),
'return_path' => 'channel/' . $channel['channel_address'],
'expanded' => true,
'editor_autocomplete' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
$o = '<div id="jot-popup">';
$o .= status_editor($a,$x);
$o .= '</div>';
}
// This page can be viewed by anybody so the query could be complicated
// First we'll see if there is a copy of the item which is owned by us - if we're logged in locally.
// If that fails (or we aren't logged in locally),
// query an item in which the observer (if logged in remotely) has cid or gid rights
// and if that fails, look for a copy of the post that has no privacy restrictions.
// If we find the post, but we don't find a copy that we're allowed to look at, this fact needs to be reported.
// find a copy of the item somewhere
$target_item = null;
$r = q("select id, uid, mid, parent_mid, item_type, item_deleted from item where mid like '%s' limit 1",
dbesc($item_hash . '%')
);
if($r) {
$target_item = $r[0];
}
$r = null;
if($target_item['item_type'] == ITEM_TYPE_WEBPAGE) {
$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",
intval($target_item['uid']),
intval($target_item['id'])
);
if($x && $y) {
goaway(z_root() . '/page/' . $x[0]['channel_address'] . '/' . $y[0]['sid']);
}
else {
notice( t('Page not found.') . EOL);
return '';
}
}
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
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)) {
$o .= '<div id="live-display"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; </script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'display',
'$uid' => '0',
'$gid' => '0',
'$cid' => '0',
'$cmin' => '0',
'$cmax' => '99',
'$star' => '0',
'$liked' => '0',
'$conv' => '0',
'$spam' => '0',
'$fh' => '0',
'$nouveau' => '0',
'$wall' => '0',
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$search' => '',
'$order' => '',
'$file' => '',
'$cats' => '',
'$tags' => '',
'$dend' => '',
'$dbegin' => '',
'$verb' => '',
'$mid' => $item_hash
));
}
$observer_hash = get_observer_hash();
$item_normal = item_normal();
$sql_extra = public_permissions_sql($observer_hash);
if(($update && $load) || ($checkjs->disabled())) {
$updateable = false;
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']),intval(\App::$pager['start']));
if($load || ($checkjs->disabled())) {
$r = null;
require_once('include/identity.php');
$sys = get_sys_channel();
$sysid = $sys['channel_id'];
if(local_channel()) {
$r = q("SELECT * from item
WHERE uid = %d
and mid = '%s'
$item_normal
limit 1",
intval(local_channel()),
dbesc($target_item['parent_mid'])
);
if($r) {
$updateable = true;
}
}
if($r === null) {
// in case somebody turned off public access to sys channel content using permissions
// make that content unsearchable by ensuring the owner_xchan can't match
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
$sysid = 0;
$r = q("SELECT * from item
WHERE mid = '%s'
AND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = ''
AND `item`.`deny_gid` = '' AND item_private = 0 )
and owner_xchan in ( " . stream_perms_xchans(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
OR uid = %d )
$sql_extra )
$item_normal
limit 1",
dbesc($target_item['parent_mid']),
intval($sysid)
);
}
}
}
elseif($update && !$load) {
$r = null;
require_once('include/identity.php');
$sys = get_sys_channel();
$sysid = $sys['channel_id'];
if(local_channel()) {
$r = q("SELECT * from item
WHERE uid = %d
and mid = '%s'
$item_normal
$simple_update
limit 1",
intval(local_channel()),
dbesc($target_item['parent_mid'])
);
if($r) {
$updateable = true;
}
}
if($r === null) {
// in case somebody turned off public access to sys channel content using permissions
// make that content unsearchable by ensuring the owner_xchan can't match
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
$sysid = 0;
$r = q("SELECT * from item
WHERE mid = '%s'
AND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = ''
AND `item`.`deny_gid` = '' AND item_private = 0 )
and owner_xchan in ( " . stream_perms_xchans(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
OR uid = %d )
$sql_extra )
$item_normal
$simple_update
limit 1",
dbesc($target_item['parent_mid']),
intval($sysid)
);
}
$_SESSION['loadtime'] = datetime_convert();
}
else {
$r = array();
}
if($r) {
$parents_str = ids_to_querystr($r,'id');
if($parents_str) {
$items = q("SELECT `item`.*, `item`.`id` AS `item_id`
FROM `item`
WHERE parent in ( %s ) $item_normal ",
dbesc($parents_str)
);
xchan_query($items);
$items = fetch_post_tags($items,true);
$items = conv_sort($items,'created');
}
} else {
$items = array();
}
if ($checkjs->disabled()) {
$o .= conversation($a, $items, 'display', $update, 'traditional');
if ($items[0]['title'])
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
}
else {
$o .= conversation($a, $items, 'display', $update, 'client');
}
if($updateable) {
$x = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 AND uid = %d and parent = %d ",
intval(local_channel()),
intval($r[0]['parent'])
);
}
$o .= '<div id="content-complete"></div>';
return $o;
/*
elseif((! $update) && (! {
$r = q("SELECT `id`, item_flags FROM `item` WHERE `id` = '%s' OR `mid` = '%s' LIMIT 1",
dbesc($item_hash),
dbesc($item_hash)
);
if($r) {
if(intval($r[0]['item_deleted'])) {
notice( t('Item has been removed.') . EOL );
}
else {
notice( t('Permission denied.') . EOL );
}
}
else {
notice( t('Item not found.') . EOL );
}
}
*/
}
}

145
Zotlabs/Module/Dreport.php Normal file
View File

@@ -0,0 +1,145 @@
<?php
namespace Zotlabs\Module;
class Dreport extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return;
}
$table = 'item';
$channel = \App::get_channel();
$mid = ((argc() > 1) ? argv(1) : '');
if($mid === 'mail') {
$table = 'mail';
$mid = ((argc() > 2) ? argv(2) : '');
}
if(! $mid) {
notice( t('Invalid message') . EOL);
return;
}
switch($table) {
case 'item':
$i = q("select id from item where mid = '%s' and author_xchan = '%s' ",
dbesc($mid),
dbesc($channel['channel_hash'])
);
break;
case 'mail':
$i = q("select id from mail where mid = '%s' and from_xchan = '%s'",
dbesc($mid),
dbesc($channel['channel_hash'])
);
break;
default:
break;
}
if(! $i) {
notice( t('Permission denied') . EOL);
return;
}
$r = q("select * from dreport where dreport_xchan = '%s' and dreport_mid = '%s'",
dbesc($channel['channel_hash']),
dbesc($mid)
);
if(! $r) {
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'],' ')));
// This has two purposes: 1. make the delivery report strings translateable, and
// 2. assign an ordering to item delivery results so we can group them and provide
// a readable report with more interesting events listed toward the top and lesser
// interesting items towards the bottom
switch($r[$x]['dreport_result']) {
case 'channel sync processed':
$r[$x]['gravity'] = 0;
$r[$x]['dreport_result'] = t('channel sync processed');
break;
case 'queued':
$r[$x]['gravity'] = 2;
$r[$x]['dreport_result'] = t('queued');
break;
case 'posted':
$r[$x]['gravity'] = 3;
$r[$x]['dreport_result'] = t('posted');
break;
case 'accepted for delivery':
$r[$x]['gravity'] = 4;
$r[$x]['dreport_result'] = t('accepted for delivery');
break;
case 'updated':
$r[$x]['gravity'] = 5;
$r[$x]['dreport_result'] = t('updated');
case 'update ignored':
$r[$x]['gravity'] = 6;
$r[$x]['dreport_result'] = t('update ignored');
break;
case 'permission denied':
$r[$x]['dreport_result'] = t('permission denied');
$r[$x]['gravity'] = 6;
break;
case 'recipient not found':
$r[$x]['dreport_result'] = t('recipient not found');
break;
case 'mail recalled':
$r[$x]['dreport_result'] = t('mail recalled');
break;
case 'duplicate mail received':
$r[$x]['dreport_result'] = t('duplicate mail received');
break;
case 'mail delivered':
$r[$x]['dreport_result'] = t('mail delivered');
break;
default:
$r[$x]['gravity'] = 1;
break;
}
}
usort($r,'self::dreport_gravity_sort');
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>';
}
$o .= '</table>';
$o .= '</div>';
return $o;
}
private static function dreport_gravity_sort($a,$b) {
if($a['gravity'] == $b['gravity']) {
if($a['name'] === $b['name'])
return strcmp($a['dreport_time'],$b['dreport_time']);
return strcmp($a['name'],$b['name']);
}
return (($a['gravity'] > $b['gravity']) ? 1 : (-1));
}
}

View File

@@ -0,0 +1,143 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
class Editblock extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
// Figure out which post we're editing
$post_id = ((argc() > 2) ? intval(argv(2)) : 0);
if(! ($post_id && $owner)) {
notice( t('Item not found') . EOL);
return;
}
$itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1",
intval($post_id),
intval($owner)
);
if($itm) {
$item_id = q("select * from item_id where service = 'BUILDBLOCK' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$block_title = $item_id[0]['sid'];
}
else {
notice( t('Item not found') . EOL);
return;
}
$mimetype = $itm[0]['mimetype'];
$rp = 'blocks/' . $channel['channel_address'];
$x = array(
'nickname' => $channel['channel_address'],
'bbco_autocomplete'=> (($mimetype == 'text/bbcode') ? 'bbcode' : 'comanche-block'),
'return_path' => $rp,
'webpage' => ITEM_TYPE_BLOCK,
'ptlabel' => t('Block Name'),
'button' => t('Edit'),
'writefiles' => (($mimetype == 'text/bbcode') ? perm_is_allowed($owner, get_observer_hash(), 'write_storage') : false),
'weblink' => (($mimetype == 'text/bbcode') ? t('Insert web link') : false),
'hide_voting' => true,
'hide_future' => true,
'hide_location' => true,
'hide_expire' => true,
'showacl' => false,
'ptyp' => $itm[0]['type'],
'mimeselect' => true,
'mimetype' => $itm[0]['mimetype'],
'body' => undo_post_tagging($itm[0]['body']),
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'placeholdertitle' => t('Title (optional)'),
'pagetitle' => $block_title,
'profile_uid' => (intval($channel['channel_id'])),
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x);
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Block'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$id' => $itm[0]['id'],
'$editor' => $editor
));
return $o;
}
}

View File

@@ -0,0 +1,145 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
class Editlayout extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
// Figure out which post we're editing
$post_id = ((argc() > 2) ? intval(argv(2)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
// Now we've got a post and an owner, let's find out if we're allowed to edit it
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
$itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1",
intval($post_id),
intval($owner)
);
$item_id = q("select * from item_id where service = 'PDL' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$layout_title = $item_id[0]['sid'];
$rp = 'layouts/' . $which;
$x = array(
'webpage' => ITEM_TYPE_PDL,
'nickname' => $channel['channel_address'],
'editor_autocomplete'=> true,
'bbco_autocomplete'=> 'comanche',
'return_path' => $rp,
'button' => t('Edit'),
'hide_voting' => true,
'hide_future' => true,
'hide_expire' => true,
'hide_location' => true,
'hide_weblink' => true,
'hide_attach' => true,
'hide_preview' => true,
'ptyp' => $itm[0]['obj_type'],
'body' => undo_post_tagging($itm[0]['body']),
'post_id' => $post_id,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'pagetitle' => $layout_title,
'ptlabel' => t('Layout Name'),
'placeholdertitle' => t('Layout Description (Optional)'),
'showacl' => false,
'profile_uid' => intval($owner),
);
$editor = status_editor($a, $x);
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Layout'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$id' => $itm[0]['id'],
'$editor' => $editor
));
return $o;
}
}

114
Zotlabs/Module/Editpost.php Normal file
View File

@@ -0,0 +1,114 @@
<?php
namespace Zotlabs\Module; /** @file */
require_once('include/acl_selectors.php');
require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/taxonomy.php');
require_once('include/conversation.php');
class Editpost extends \Zotlabs\Web\Controller {
function get() {
$o = '';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
$itm = q("SELECT * FROM `item` WHERE `id` = %d AND ( owner_xchan = '%s' OR author_xchan = '%s' ) LIMIT 1",
intval($post_id),
dbesc(get_observer_hash()),
dbesc(get_observer_hash())
);
if(! count($itm)) {
notice( t('Item is not editable') . EOL);
return;
}
if($itm[0]['resource_type'] === 'event' && $itm[0]['resource_id']) {
goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1');
}
$owner_uid = $itm[0]['uid'];
$channel = \App::get_channel();
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);
if($itm[0]['body'])
$itm[0]['body'] = crypto_unencapsulate(json_decode_plus($itm[0]['body']),$key);
}
$category = '';
$catsenabled = ((feature_enabled($owner_uid,'categories')) ? 'categories' : '');
if ($catsenabled){
$itm = fetch_post_tags($itm);
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($category))
$category .= ', ';
$category .= $cat['term'];
}
}
if($itm[0]['attach']) {
$j = json_decode($itm[0]['attach'],true);
if($j) {
foreach($j as $jj) {
$itm[0]['body'] .= "\n" . '[attachment]' . basename($jj['href']) . ',' . $jj['revision'] . '[/attachment]' . "\n";
}
}
}
$x = array(
'nickname' => $channel['channel_address'],
'editor_autocomplete'=> true,
'bbco_autocomplete'=> 'bbcode',
'return_path' => $_SESSION['return_url'],
'button' => t('Edit'),
'hide_voting' => true,
'hide_future' => true,
'hide_location' => true,
'mimetype' => $itm[0]['mimetype'],
'ptyp' => $itm[0]['obj_type'],
'body' => undo_post_tagging($itm[0]['body']),
'post_id' => $post_id,
'defloc' => $channel['channel_location'],
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'category' => $category,
'showacl' => false,
'profile_uid' => $owner_uid,
'catsenabled' => $catsenabled,
'hide_expire' => true,
'bbcode' => true
);
$editor = status_editor($a, $x);
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit post'),
'$editor' => $editor
));
return $o;
}
}

View File

@@ -0,0 +1,179 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
require_once('include/PermissionDescription.php');
class Editwebpage extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
// Figure out which post we're editing
$post_id = ((argc() > 2) ? intval(argv(2)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
// We've already figured out which item we want and whose copy we need,
// so we don't need anything fancy here
$sql_extra = item_permissions_sql($owner);
$itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s $sql_extra LIMIT 1",
intval($post_id),
intval($owner)
);
if(! $itm) {
notice( t('Permission denied.') . EOL);
return;
}
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);
if($itm[0]['body'])
$itm[0]['body'] = crypto_unencapsulate(json_decode_plus($itm[0]['body']),$key);
}
$item_id = q("select * from item_id where service = 'WEBPAGE' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$page_title = $item_id[0]['sid'];
$mimetype = $itm[0]['mimetype'];
if($mimetype === 'application/x-php') {
if((! $uid) || ($uid != $itm[0]['uid'])) {
notice( t('Permission denied.') . EOL);
return;
}
}
$layout = $itm[0]['layout_mid'];
$tpl = get_markup_template("jot.tpl");
$rp = 'webpages/' . $which;
$x = array(
'nickname' => $channel['channel_address'],
'bbco_autocomplete'=> (($mimetype == 'text/bbcode') ? 'bbcode' : ''),
'return_path' => $rp,
'webpage' => ITEM_TYPE_WEBPAGE,
'ptlabel' => t('Page link'),
'pagetitle' => $page_title,
'writefiles' => (($mimetype == 'text/bbcode') ? perm_is_allowed($owner, get_observer_hash(), 'write_storage') : false),
'button' => t('Edit'),
'weblink' => (($mimetype == 'text/bbcode') ? t('Insert web link') : false),
'hide_location' => true,
'hide_voting' => true,
'ptyp' => $itm[0]['type'],
'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')),
'showacl' => ($is_owner) ? true : false,
'mimetype' => $mimetype,
'mimeselect' => true,
'layout' => $layout,
'layoutselect' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'lockstate' => (((strlen($itm[0]['allow_cid'])) || (strlen($itm[0]['allow_gid'])) || (strlen($itm[0]['deny_cid'])) || (strlen($itm[0]['deny_gid']))) ? 'lock' : 'unlock'),
'profile_uid' => (intval($owner)),
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x);
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Webpage'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$editor' => $editor,
'$id' => $itm[0]['id']
));
return $o;
}
}

717
Zotlabs/Module/Events.php Normal file
View File

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

136
Zotlabs/Module/Fbrowser.php Normal file
View File

@@ -0,0 +1,136 @@
<?php
namespace Zotlabs\Module;
/**
* @package Friendica\modules
* @subpackage FileBrowser
* @author Fabio Comuni <fabrixxm@kirgroup.com>
*/
require_once('include/photo/photo_driver.php');
/**
* @param App $a
*/
class Fbrowser extends \Zotlabs\Web\Controller {
function get(){
if (!local_channel())
killme();
if (\App::$argc==1)
killme();
//echo "<pre>"; var_dump(\App::$argv); killme();
switch(\App::$argv[1]){
case "image":
$path = array( array(z_root()."/fbrowser/image/", t("Photos")));
$albums = false;
$sql_extra = "";
$sql_extra2 = " ORDER BY created DESC LIMIT 0, 10";
if (\App::$argc==2){
$albums = q("SELECT distinct(`album`) AS `album` FROM `photo` WHERE `uid` = %d ",
intval(local_channel())
);
// anon functions only from 5.3.0... meglio tardi che mai..
$albums = array_map( "self::folder1" , $albums);
}
$album = "";
if (\App::$argc==3){
$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);
}
$r = q("SELECT `resource_id`, `id`, `filename`, type, min(`scale`) AS `hiq`,max(`scale`) AS `loq`, `description`
FROM `photo` WHERE `uid` = %d $sql_extra
GROUP BY `resource_id` $sql_extra2",
intval(local_channel())
);
$files = array_map("self::files1", $r);
$tpl = get_markup_template("filebrowser.tpl");
echo replace_macros($tpl, array(
'$type' => 'image',
'$baseurl' => z_root(),
'$path' => $path,
'$folders' => $albums,
'$files' =>$files,
'$cancel' => t('Cancel'),
));
break;
case "file":
if (\App::$argc==2){
$files = q("SELECT id, filename, filetype FROM `attach` WHERE `uid` = %d ",
intval(local_channel())
);
$files = array_map("self::files2", $files);
//echo "<pre>"; var_dump($files); killme();
$tpl = get_markup_template("filebrowser.tpl");
echo replace_macros($tpl, array(
'$type' => 'file',
'$baseurl' => z_root(),
'$path' => array( array(z_root()."/fbrowser/image/", t("Files")) ),
'$folders' => false,
'$files' =>$files,
'$cancel' => t('Cancel'),
));
}
break;
}
killme();
}
private static function folder1($el){
return array(bin2hex($el['album']),$el['album']);
}
private static function files1($rr){
$ph = photo_factory('');
$types = $ph->supportedTypes();
$ext = $types[$rr['type']];
$filename_e = $rr['filename'];
return array(
z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['hiq'] . '.' .$ext,
$filename_e,
z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['loq'] . '.'. $ext
);
}
private static function files2($rr){
list($m1,$m2) = explode("/",$rr['filetype']);
$filetype = ( (file_exists("images/icons/$m1.png"))?$m1:"zip");
if(\App::get_template_engine() === 'internal') {
$filename_e = template_escape($rr['filename']);
}
else {
$filename_e = $rr['filename'];
}
return array( z_root() . '/attach/' . $rr['id'], $filename_e, z_root() . '/images/icons/16/' . $filetype . '.png');
}
}

48
Zotlabs/Module/Feed.php Normal file
View File

@@ -0,0 +1,48 @@
<?php
namespace Zotlabs\Module;
require_once('include/items.php');
class Feed extends \Zotlabs\Web\Controller {
function init() {
$params = array();
$params['begin'] = ((x($_REQUEST,'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE);
$params['end'] = ((x($_REQUEST,'date_end')) ? $_REQUEST['date_end'] : '');
$params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml');
$params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0);
$params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0);
$params['start'] = ((x($params,'start')) ? intval($params['start']) : 0);
$params['records'] = ((x($params,'records')) ? intval($params['records']) : 40);
$params['direction'] = ((x($params,'direction')) ? dbesc($params['direction']) : 'desc');
$params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : '');
$channel = '';
if(argc() > 1) {
$r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1",
dbesc(argv(1))
);
if(!($r && count($r)))
killme();
$channel = $r[0];
if((intval(get_config('system','block_public'))) && (! get_account_id()))
killme();
logger('mod_feed: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']);
echo get_public_feed($channel,$params);
killme();
}
}
}

71
Zotlabs/Module/Ffsapi.php Normal file
View File

@@ -0,0 +1,71 @@
<?php
namespace Zotlabs\Module;
class Ffsapi extends \Zotlabs\Web\Controller {
function get() {
$baseurl = z_root();
$name = get_config('system','sitename');
$description = t('Share content from Firefox to $Projectname');
$author = 'Mike Macgirvin';
$homepage = 'http://hubzilla.org';
$activate = t('Activate the Firefox $Projectname provider');
$s = <<< EOT
<script>
var baseurl = '$baseurl';
var data = {
"origin": baseurl,
// currently required
"name": '$name',
"iconURL": baseurl+"/images/hz-16.png",
"icon32URL": baseurl+"/images/hz-32.png",
"icon64URL": baseurl+"/images/hz-64.png",
// at least one of these must be defined
// "workerURL": baseurl+"/worker.js",
// "sidebarURL": baseurl+"/sidebar.htm",
"shareURL": baseurl+"/rpost?f=&url=%{url}",
// status buttons are scheduled for Firefox 26 or 27
//"statusURL": baseurl+"/statusPanel.html",
// social bookmarks are available in Firefox 26
"markURL": baseurl+"/rbmark?f=&url=%{url}&title=%{title}",
// icons should be 32x32 pixels
// "markedIcon": baseurl+"/images/checkbox-checked-32.png",
// "unmarkedIcon": baseurl+"/images/checkbox-unchecked-32.png",
"unmarkedIcon": baseurl+"/images/hz-bookmark-32.png",
// should be available for display purposes
"description": "$description",
"author": "$author",
"homepageURL": "$homepage",
// optional
"version": "1.0"
}
function activate(node) {
var event = new CustomEvent("ActivateSocialFeature");
var jdata = JSON.stringify(data);
node.setAttribute("data-service", JSON.stringify(data));
node.dispatchEvent(event);
}
</script>
<button onclick="activate(this)" title="$activate" class="btn btn-primary">$activate</button>
EOT;
return $s;
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace Zotlabs\Module;
require_once('include/zot.php');
require_once('include/crypto.php');
/* fix missing or damaged hublocs */
class Fhublocs extends \Zotlabs\Web\Controller {
function get() {
if(! is_site_admin())
return;
$o = '';
$r = q("select * from channel where channel_removed = 0");
$sitekey = get_config('system','pubkey');
if($r) {
foreach($r as $rr) {
$found = false;
$primary_address = '';
$x = zot_get_hublocs($rr['channel_hash']);
if($x) {
foreach($x as $xx) {
if($xx['hubloc_url'] === z_root() && $xx['hubloc_sitekey'] === $sitekey) {
$found = true;
break;
}
}
if($found) {
$o .= 'Hubloc exists for ' . $rr['channel_name'] . EOL;
continue;
}
}
$y = q("select xchan_addr from xchan where xchan_hash = '%s' limit 1",
dbesc($rr['channel_hash'])
);
if($y)
$primary_address = $y[0]['xchan_addr'];
$hub_address = $rr['channel']['channel_address'] . '@' . \App::get_hostname();
$primary = (($hub_address === $primary_address) ? 1 : 0);
if(! $y)
$primary = 1;
$m = q("delete from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ",
dbesc($rr['channel_hash']),
dbesc(z_root())
);
// Create a verified hub location pointing to this site.
$h = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_primary, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_network )
values ( '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
dbesc($rr['channel_guid']),
dbesc($rr['channel_guid_sig']),
dbesc($rr['channel_hash']),
dbesc($rr['channel_address'] . '@' . \App::get_hostname()),
intval($primary),
dbesc(z_root()),
dbesc(base64url_encode(rsa_sign(z_root(),$rr['channel_prvkey']))),
dbesc(\App::get_hostname()),
dbesc(z_root() . '/post'),
dbesc($sitekey),
dbesc('zot')
);
if($h)
$o . 'local hubloc created for ' . $rr['channel_name'] . EOL;
else
$o .= 'DB update failed for ' . $rr['channel_name'] . EOL;
}
return $o;
}
}
}

61
Zotlabs/Module/Filer.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
namespace Zotlabs\Module;
require_once('include/security.php');
require_once('include/bbcode.php');
require_once('include/items.php');
class Filer extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
killme();
}
$term = unxmlify(trim($_GET['term']));
$item_id = ((\App::$argc > 1) ? intval(\App::$argv[1]) : 0);
logger('filer: tag ' . $term . ' item ' . $item_id);
if($item_id && strlen($term)){
// file item
store_item_tag(local_channel(),$item_id,TERM_OBJ_POST,TERM_FILE,$term,'');
// protect the entire conversation from periodic expiration
$r = q("select parent from item where id = %d and uid = %d limit 1",
intval($item_id),
intval(local_channel())
);
if($r) {
$x = q("update item set item_retained = 1 where id = %d and uid = %d",
intval($r[0]['parent']),
intval(local_channel())
);
}
}
else {
$filetags = array();
$r = q("select distinct(term) from term where uid = %d and type = %d order by term asc",
intval(local_channel()),
intval(TERM_FILE)
);
if(count($r)) {
foreach($r as $rr)
$filetags[] = $rr['term'];
}
$tpl = get_markup_template("filer_dialog.tpl");
$o = replace_macros($tpl, array(
'$field' => array('term', t("Save to Folder:"), '', '', $filetags, t('- select -')),
'$submit' => t('Save'),
));
echo $o;
}
killme();
}
}

39
Zotlabs/Module/Filerm.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
namespace Zotlabs\Module;
class Filerm extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
killme();
}
$term = trim($_GET['term']);
$cat = trim($_GET['cat']);
$category = (($cat) ? true : false);
if($category)
$term = $cat;
$item_id = ((\App::$argc > 1) ? intval(\App::$argv[1]) : 0);
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'",
intval(local_channel()),
intval(($category) ? TERM_CATEGORY : TERM_FILE),
intval($item_id),
dbesc($term)
);
}
if(x($_SESSION,'return_url'))
goaway(z_root() . '/' . $_SESSION['return_url']);
killme();
}
}

View File

@@ -0,0 +1,175 @@
<?php
namespace Zotlabs\Module;
/**
* @file mod/filestorage.php
*
*/
require_once('include/attach.php');
require_once('include/PermissionDescription.php');
/**
*
* @param object &$a
*/
class Filestorage extends \Zotlabs\Web\Controller {
function post() {
$channel_id = ((x($_POST, 'uid')) ? intval($_POST['uid']) : 0);
if((! $channel_id) || (! local_channel()) || ($channel_id != local_channel())) {
notice( t('Permission denied.') . EOL);
return;
}
$recurse = ((x($_POST, 'recurse')) ? intval($_POST['recurse']) : 0);
$resource = ((x($_POST, 'filehash')) ? notags($_POST['filehash']) : '');
$notify = ((x($_POST, 'notify')) ? intval($_POST['notify']) : 0);
if(! $resource) {
notice(t('Item not found.') . EOL);
return;
}
$channel = \App::get_channel();
$acl = new \Zotlabs\Access\AccessList($channel);
$acl->set_from_array($_REQUEST);
$x = $acl->get();
$cloudPath = get_parent_cloudpath($channel_id, $channel['channel_address'], $resource);
//get the object before permissions change so we can catch eventual former allowed members
$object = get_file_activity_object($channel_id, $resource, $cloudPath);
attach_change_permissions($channel_id, $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse);
file_activity($channel_id, $object, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], 'post', $notify);
goaway($cloudPath);
}
function get() {
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$r = q("select * from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$channel = $r[0];
$owner = intval($r[0]['channel_id']);
}
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner, $ob_hash);
if(! $perms['view_storage']) {
notice( t('Permission denied.') . EOL);
return;
}
// Since we have ACL'd files in the wild, but don't have ACL here yet, we
// need to return for anyone other than the owner, despite the perms check for now.
$is_owner = (((local_channel()) && ($owner == local_channel())) ? true : false);
if(! $is_owner) {
info( t('Permission Denied.') . EOL );
return;
}
if(argc() > 3 && argv(3) === 'delete') {
if(! $perms['write_storage']) {
notice( t('Permission denied.') . EOL);
return;
}
$file = intval(argv(2));
$r = q("SELECT hash FROM attach WHERE id = %d AND uid = %d LIMIT 1",
dbesc($file),
intval($owner)
);
if(! $r) {
notice( t('File not found.') . EOL);
goaway(z_root() . '/cloud/' . $which);
}
$f = $r[0];
$channel = \App::get_channel();
$parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']);
attach_delete($owner, $f['hash']);
goaway($parentpath);
}
if(argc() > 3 && argv(3) === 'edit') {
require_once('include/acl_selectors.php');
if(! $perms['write_storage']) {
notice( t('Permission denied.') . EOL);
return;
}
$file = intval(argv(2));
$r = q("select id, uid, folder, filename, revision, flags, is_dir, os_storage, hash, allow_cid, allow_gid, deny_cid, deny_gid from attach where id = %d and uid = %d limit 1",
intval($file),
intval($owner)
);
$f = $r[0];
$channel = \App::get_channel();
$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'));
$is_a_dir = (intval($f['is_dir']) ? true : false);
$lockstate = (($f['allow_cid'] || $f['allow_gid'] || $f['deny_cid'] || $f['deny_gid']) ? 'lock' : 'unlock');
// 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,
'$cloudpath' => z_root() . '/' . $encoded_path,
'$parentpath' => $parentpath,
'$uid' => $channel['channel_id'],
'$channelnick' => $channel['channel_address'],
'$permissions' => t('Permissions'),
'$aclselect' => $aclselect_e,
'$lockstate' => $lockstate,
'$permset' => t('Set/edit permissions'),
'$recurse' => array('recurse', t('Include all files and sub folders'), 0, '', array(t('No'), t('Yes'))),
'$backlink' => t('Return to file list'),
'$isadir' => $is_a_dir,
'$cpdesc' => t('Copy/paste this code to attach file to a post'),
'$cpldesc' => t('Copy/paste this URL to link file from a web page'),
'$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')))
));
echo $o;
killme();
}
goaway(z_root() . '/cloud/' . $which);
}
}

68
Zotlabs/Module/Follow.php Normal file
View File

@@ -0,0 +1,68 @@
<?php
namespace Zotlabs\Module;
require_once('include/follow.php');
class Follow extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel()) {
return;
}
$uid = local_channel();
$url = notags(trim($_REQUEST['url']));
$return_url = $_SESSION['return_url'];
$confirm = intval($_REQUEST['confirm']);
$channel = \App::get_channel();
// Warning: Do not edit the following line. The first symbol is UTF-8 &#65312;
$url = str_replace('@','@',$url);
$result = new_contact($uid,$url,$channel,true,$confirm);
if($result['success'] == false) {
if($result['message'])
notice($result['message']);
goaway($return_url);
}
info( t('Channel added.') . EOL);
$clone = array();
foreach($result['abook'] as $k => $v) {
if(strpos($k,'abook_') === 0) {
$clone[$k] = $v;
}
}
unset($clone['abook_id']);
unset($clone['abook_account']);
unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_hash'],$clone['abook_xchan']);
if($abconfig)
$clone['abconfig'] = $abconfig;
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
// 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']);
goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?f=&follow=1');
}
function get() {
if(! local_channel()) {
return login();
}
}
}

117
Zotlabs/Module/Fsuggest.php Normal file
View File

@@ -0,0 +1,117 @@
<?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;
}
}

102
Zotlabs/Module/Getfile.php Normal file
View File

@@ -0,0 +1,102 @@
<?php
namespace Zotlabs\Module;
/**
* module: getfile
*
* used for synchronising files and photos across clones
*
* The site initiating the file operation will send a sync packet to known clones.
* They will respond by building the DB structures they require, then will provide a
* post request to this site to grab the file data. This is sent as a stream direct to
* disk at the other end, avoiding memory issues.
*
* Since magic-auth cannot easily be used by the CURL process at the other end,
* we will require a signed request which includes a timestamp. This should not be
* used without SSL and is potentially vulnerable to replay if an attacker decrypts
* the SSL traffic fast enough. The amount of time slop is configurable but defaults
* to 3 minutes.
*
*/
require_once('include/Contact.php');
require_once('include/attach.php');
class Getfile extends \Zotlabs\Web\Controller {
function post() {
$hash = $_POST['hash'];
$time = $_POST['time'];
$sig = $_POST['signature'];
$resource = $_POST['resource'];
$revision = intval($_POST['revision']);
if(! $hash)
killme();
$channel = channelx_by_hash($hash);
if((! $channel) || (! $time) || (! $sig))
killme();
$slop = intval(get_pconfig($channel['channel_id'],'system','getfile_time_slop'));
if($slop < 1)
$slop = 3;
$d1 = datetime_convert('UTC','UTC',"now + $slop minutes");
$d2 = datetime_convert('UTC','UTC',"now - $slop minutes");
if(($time > $d1) || ($time < $d2)) {
logger('time outside allowable range');
killme();
}
if(! rsa_verify($hash . '.' . $time,base64url_decode($sig),$channel['channel_pubkey'])) {
logger('verify failed.');
killme();
}
$r = attach_by_hash($resource,$revision);
if(! $r['success']) {
notice( $r['message'] . EOL);
return;
}
$unsafe_types = array('text/html','text/css','application/javascript');
if(in_array($r['data']['filetype'],$unsafe_types)) {
header('Content-type: text/plain');
}
else {
header('Content-type: ' . $r['data']['filetype']);
}
header('Content-disposition: attachment; filename="' . $r['data']['filename'] . '"');
if(intval($r['data']['os_storage'])) {
$fname = dbunescbin($r['data']['data']);
if(strpos($fname,'store') !== false)
$istream = fopen($fname,'rb');
else
$istream = fopen('store/' . $channel['channel_address'] . '/' . $fname,'rb');
$ostream = fopen('php://output','wb');
if($istream && $ostream) {
pipe_streams($istream,$ostream);
fclose($istream);
fclose($ostream);
}
}
else
echo dbunescbin($r['data']['data']);
killme();
}
}

244
Zotlabs/Module/Group.php Normal file
View File

@@ -0,0 +1,244 @@
<?php
namespace Zotlabs\Module;
require_once('include/group.php');
class Group extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if((argc() == 2) && (argv(1) === 'new')) {
check_form_security_token_redirectOnErr('/group/new', 'group_edit');
$name = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
$r = group_add(local_channel(),$name,$public);
if($r) {
info( t('Privacy group created.') . EOL );
$r = group_byname(local_channel(),$name);
if($r)
goaway(z_root() . '/group/' . $r);
}
else
notice( t('Could not create privacy group.') . EOL );
goaway(z_root() . '/group');
}
if((argc() == 2) && (intval(argv(1)))) {
check_form_security_token_redirectOnErr('/group', 'group_edit');
$r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if(! $r) {
notice( t('Privacy group not found.') . EOL );
goaway(z_root() . '/connections');
}
$group = $r[0];
$groupname = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
if((strlen($groupname)) && (($groupname != $group['name']) || ($public != $group['visible']))) {
$r = q("UPDATE `groups` SET `name` = '%s', visible = %d WHERE `uid` = %d AND `id` = %d",
dbesc($groupname),
intval($public),
intval(local_channel()),
intval($group['id'])
);
if($r)
info( t('Privacy group updated.') . EOL );
}
goaway(z_root() . '/group/' . argv(1) . '/' . argv(2));
}
return;
}
function get() {
$change = false;
logger('mod_group: ' . \App::$cmd,LOGGER_DEBUG);
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return;
}
// Switch to text mode interface if we have more than 'n' contacts or group members
$switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit');
if($switchtotext === false)
$switchtotext = get_config('system','groupedit_image_limit');
if($switchtotext === false)
$switchtotext = 400;
$tpl = get_markup_template('group_edit.tpl');
$context = array('$submit' => t('Submit'));
if((argc() == 2) && (argv(1) === 'new')) {
return replace_macros($tpl, $context + array(
'$title' => t('Create a group of channels.'),
'$gname' => array('groupname',t('Privacy group name: '), '', ''),
'$gid' => 'new',
'$public' => array('public',t('Members are visible to other channels'), false, ''),
'$form_security_token' => get_form_security_token("group_edit"),
));
}
if((argc() == 3) && (argv(1) === 'drop')) {
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",
intval(argv(2)),
intval(local_channel())
);
if($r)
$result = group_rmv(local_channel(),$r[0]['name']);
if($result)
info( t('Privacy group removed.') . EOL);
else
notice( t('Unable to remove privacy group.') . EOL);
}
goaway(z_root() . '/group');
// NOTREACHED
}
if((argc() > 2) && intval(argv(1)) && argv(2)) {
check_form_security_token_ForbiddenOnErr('group_member_change', 't');
$r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1",
dbesc(base64url_decode(argv(2))),
intval(local_channel())
);
if(count($r))
$change = base64url_decode(argv(2));
}
if((argc() > 1) && (intval(argv(1)))) {
require_once('include/acl_selectors.php');
$r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if(! $r) {
notice( t('Privacy group not found.') . EOL );
goaway(z_root() . '/connections');
}
$group = $r[0];
$members = group_get_members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
if(! in_array($member['xchan_hash'],$preselected))
$preselected[] = $member['xchan_hash'];
}
if($change) {
if(in_array($change,$preselected)) {
group_rmv_member(local_channel(),$group['name'],$change);
}
else {
group_add_member(local_channel(),$group['name'],$change);
}
$members = group_get_members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
$preselected[] = $member['xchan_hash'];
}
}
$drop_tpl = get_markup_template('group_drop.tpl');
$drop_txt = replace_macros($drop_tpl, array(
'$id' => $group['id'],
'$delete' => t('Delete'),
'$form_security_token' => get_form_security_token("group_drop"),
));
$context = $context + array(
'$title' => t('Privacy group editor'),
'$gname' => array('groupname',t('Privacy group name: '),$group['name'], ''),
'$gid' => $group['id'],
'$drop' => $drop_txt,
'$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''),
'$form_security_token' => get_form_security_token('group_edit'),
);
}
if(! isset($group))
return;
$groupeditor = array(
'label_members' => t('Members'),
'members' => array(),
'label_contacts' => t('All Connected Channels'),
'contacts' => array(),
);
$sec_token = addslashes(get_form_security_token('group_member_change'));
$textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : false);
foreach($members as $member) {
if($member['xchan_url']) {
$member['archived'] = (intval($member['abook_archived']) ? true : false);
$member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
$groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode);
}
else
group_rmv_member(local_channel(),$group['name'],$member['xchan_hash']);
}
$r = q("SELECT abook.*, xchan.* FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE `abook_channel` = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc",
intval(local_channel())
);
if(count($r)) {
$textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : false);
foreach($r as $member) {
if(! in_array($member['xchan_hash'],$preselected)) {
$member['archived'] = (intval($member['abook_archived']) ? true : false);
$member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
$groupeditor['contacts'][] = micropro($member,true,'mpall', $textmode);
}
}
}
$context['$groupeditor'] = $groupeditor;
$context['$desc'] = t('Click on a channel to add or remove.');
if($change) {
$tpl = get_markup_template('groupeditor.tpl');
echo replace_macros($tpl, $context);
killme();
}
return replace_macros($tpl, $context);
}
}

60
Zotlabs/Module/Hcard.php Normal file
View File

@@ -0,0 +1,60 @@
<?php
namespace Zotlabs\Module;
class Hcard extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$profile = '';
$channel = \App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
$r = q("select profile_guid from profile where id = %d and uid = %d limit 1",
intval($profile),
intval(local_channel())
);
if(! $r)
$profile = '';
$profile = $r[0]['profile_guid'];
}
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $which .'" />' . "\r\n" ;
if(! $profile) {
$x = q("select channel_id as profile_uid from channel where channel_address = '%s' limit 1",
dbesc(argv(1))
);
if($x) {
\App::$profile = $x[0];
}
}
profile_load($a,$which,$profile);
}
function get() {
require_once('include/widgets.php');
return widget_profile(array());
}
}

146
Zotlabs/Module/Help.php Normal file
View File

@@ -0,0 +1,146 @@
<?php
namespace Zotlabs\Module;
require_once('include/help.php');
/**
* You can create local site resources in doc/Site.md and either link to doc/Home.md for the standard resources
* or use our include mechanism to include it on your local page.
*
* #include doc/Home.md;
*
* The syntax is somewhat strict.
*
*/
class Help extends \Zotlabs\Web\Controller {
function get() {
nav_set_selected('help');
if($_REQUEST['search']) {
$o .= '<div id="help-content" class="generic-content-wrapper">';
$o .= '<div class="section-title-wrapper">';
$o .= '<h2>' . t('Documentation Search') . ' - ' . htmlspecialchars($_REQUEST['search']) . '</h2>';
$o .= '</div>';
$o .= '<div class="section-content-wrapper">';
$r = search_doc_files($_REQUEST['search']);
if($r) {
$o .= '<ul class="help-searchlist">';
foreach($r as $rr) {
$dirname = dirname($rr['sid']);
$fname = basename($rr['sid']);
$fname = substr($fname,0,strrpos($fname,'.'));
$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>';
}
$o .= '</ul>';
$o .= '</div>';
$o .= '</div>';
}
return $o;
}
global $lang;
$doctype = 'markdown';
$text = '';
if(argc() > 1) {
$path = '';
for($x = 1; $x < argc(); $x ++) {
if(strlen($path))
$path .= '/';
$path .= argv($x);
}
$title = basename($path);
$text = load_doc_file('doc/' . $path . '.md');
\App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title)));
if(! $text) {
$text = load_doc_file('doc/' . $path . '.bb');
if($text)
$doctype = 'bbcode';
\App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('_',' ',notags($title)));
}
if(! $text) {
$text = load_doc_file('doc/' . $path . '.html');
if($text)
$doctype = 'html';
\App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title)));
}
}
if(! $text) {
$text = load_doc_file('doc/Site.md');
\App::$page['title'] = t('Help');
}
if(! $text) {
$doctype = 'bbcode';
$text = load_doc_file('doc/main.bb');
\App::$page['title'] = t('Help');
}
if(! strlen($text)) {
header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . t('Not Found'));
$tpl = get_markup_template("404.tpl");
return replace_macros($tpl, array(
'$message' => t('Page not found.' )
));
}
if($doctype === 'html')
$content = $text;
if($doctype === 'markdown') {
require_once('library/markdown.php');
# escape #include tags
$text = preg_replace('/#include/ism', '%%include', $text);
$content = Markdown($text);
$content = preg_replace('/%%include/ism', '#include', $content);
}
if($doctype === 'bbcode') {
require_once('include/bbcode.php');
$content = bbcode($text);
// bbcode retargets external content to new windows. This content is internal.
$content = str_replace(' target="_blank"','',$content);
}
$content = preg_replace_callback("/#include (.*?)\;/ism", 'self::preg_callback_help_include', $content);
return replace_macros(get_markup_template("help.tpl"), array(
'$title' => t('$Projectname Documentation'),
'$content' => translate_projectname($content)
));
}
private static function preg_callback_help_include($matches) {
if($matches[1]) {
$include = str_replace($matches[0],load_doc_file($matches[1]),$matches[0]);
if(preg_match('/\.bb$/', $matches[1]) || preg_match('/\.txt$/', $matches[1])) {
require_once('include/bbcode.php');
$include = bbcode($include);
$include = str_replace(' target="_blank"','',$include);
}
elseif(preg_match('/\.md$/', $matches[1])) {
require_once('library/markdown.php');
$include = Markdown($include);
}
return $include;
}
}
}

89
Zotlabs/Module/Home.php Normal file
View File

@@ -0,0 +1,89 @@
<?php
namespace Zotlabs\Module;
require_once('include/items.php');
require_once('include/conversation.php');
class Home extends \Zotlabs\Web\Controller {
function init() {
$ret = array();
call_hooks('home_init',$ret);
$splash = ((argc() > 1 && argv(1) === 'splash') ? true : false);
$channel = \App::get_channel();
if(local_channel() && $channel && $channel['xchan_url'] && ! $splash) {
$dest = $channel['channel_startpage'];
if(! $dest)
$dest = get_pconfig(local_channel(),'system','startpage');
if(! $dest)
$dest = get_config('system','startpage');
if(! $dest)
$dest = z_root() . '/network';
goaway($dest);
}
if(get_account_id() && ! $splash) {
goaway(z_root() . '/new_channel');
}
}
function get($update = 0, $load = false) {
$o = '';
if(x($_SESSION,'theme'))
unset($_SESSION['theme']);
if(x($_SESSION,'mobile_theme'))
unset($_SESSION['mobile_theme']);
$splash = ((argc() > 1 && argv(1) === 'splash') ? true : false);
call_hooks('home_content',$o);
if($o)
return $o;
$frontpage = get_config('system','frontpage');
if($frontpage) {
if(strpos($frontpage,'include:') !== false) {
$file = trim(str_replace('include:' , '', $frontpage));
if(file_exists($file)) {
\App::$page['template'] = 'full';
\App::$page['title'] = t('$Projectname');
$o .= file_get_contents($file);
return $o;
}
}
if(strpos($frontpage,'http') !== 0)
$frontpage = z_root() . '/' . $frontpage;
if(intval(get_config('system','mirror_frontpage'))) {
$o = '<html><head><title>' . t('$Projectname') . '</title></head><body style="margin: 0; padding: 0; border: none;" ><iframe src="' . $frontpage . '" width="100%" height="100%" style="margin: 0; padding: 0; border: none;" ></iframe></body></html>';
echo $o;
killme();
}
goaway($frontpage);
}
$sitename = get_config('system','sitename');
if($sitename)
$o .= '<h1 class="home-welcome">' . sprintf( t("Welcome to %s") ,$sitename) . '</h1>';
$loginbox = get_config('system','login_on_homepage');
if(intval($loginbox) || $loginbox === false)
$o .= login((\App::$config['system']['register_policy'] == REGISTER_CLOSED) ? 0 : 1);
return $o;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Zotlabs\Module;
class Hostxrd extends \Zotlabs\Web\Controller {
function init() {
header('Access-Control-Allow-Origin: *');
header("Content-type: application/xrd+xml");
logger('hostxrd',LOGGER_DEBUG);
$tpl = get_markup_template('xrd_host.tpl');
$x = replace_macros(get_markup_template('xrd_host.tpl'), array(
'$zhost' => \App::get_hostname(),
'$zroot' => z_root()
));
$arr = array('xrd' => $x);
call_hooks('hostxrd',$arr);
echo $arr['xrd'];
killme();
}
}

319
Zotlabs/Module/Id.php Normal file
View File

@@ -0,0 +1,319 @@
<?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');
}
}

207
Zotlabs/Module/Impel.php Normal file
View File

@@ -0,0 +1,207 @@
<?php
namespace Zotlabs\Module; /** @file */
// import page design element
require_once('include/menu.php');
class Impel extends \Zotlabs\Web\Controller {
function init() {
$ret = array('success' => false);
if(! local_channel())
json_return_and_die($ret);
logger('impel: ' . print_r($_REQUEST,true), LOGGER_DATA);
$elm = $_REQUEST['element'];
$x = base64url_decode($elm);
if(! $x)
json_return_and_die($ret);
$j = json_decode($x,true);
if(! $j)
json_return_and_die($ret);
$channel = \App::get_channel();
$arr = array();
$is_menu = false;
// a portable menu has its links rewritten with the local baseurl
$portable_menu = false;
switch($j['type']) {
case 'webpage':
$arr['item_type'] = ITEM_TYPE_WEBPAGE;
$namespace = 'WEBPAGE';
$installed_type = t('webpage');
break;
case 'block':
$arr['item_type'] = ITEM_TYPE_BLOCK;
$namespace = 'BUILDBLOCK';
$installed_type = t('block');
break;
case 'layout':
$arr['item_type'] = ITEM_TYPE_PDL;
$namespace = 'PDL';
$installed_type = t('layout');
break;
case 'portable-menu':
$portable_menu = true;
// fall through
case 'menu':
$is_menu = true;
$installed_type = t('menu');
break;
default:
logger('mod_impel: unrecognised element type' . print_r($j,true));
break;
}
if($is_menu) {
$m = array();
$m['menu_channel_id'] = local_channel();
$m['menu_name'] = $j['pagetitle'];
$m['menu_desc'] = $j['desc'];
if($j['created'])
$m['menu_created'] = datetime_convert($j['created']);
if($j['edited'])
$m['menu_edited'] = datetime_convert($j['edited']);
$m['menu_flags'] = 0;
if($j['flags']) {
if(in_array('bookmark',$j['flags']))
$m['menu_flags'] |= MENU_BOOKMARK;
if(in_array('system',$j['flags']))
$m['menu_flags'] |= MENU_SYSTEM;
}
$menu_id = menu_create($m);
if($menu_id) {
if(is_array($j['items'])) {
foreach($j['items'] as $it) {
$mitem = array();
$mitem['mitem_link'] = str_replace('[baseurl]',z_root(),$it['link']);
$mitem['mitem_desc'] = escape_tags($it['desc']);
$mitem['mitem_order'] = intval($it['order']);
if(is_array($it['flags'])) {
$mitem['mitem_flags'] = 0;
if(in_array('zid',$it['flags']))
$mitem['mitem_flags'] |= MENU_ITEM_ZID;
if(in_array('new-window',$it['flags']))
$mitem['mitem_flags'] |= MENU_ITEM_NEWWIN;
if(in_array('chatroom',$it['flags']))
$mitem['mitem_flags'] |= MENU_ITEM_CHATROOM;
}
menu_add_item($menu_id,local_channel(),$mitem);
}
if($j['edited']) {
$x = q("update menu set menu_edited = '%s' where menu_id = %d and menu_channel_id = %d",
dbesc(datetime_convert('UTC','UTC',$j['edited'])),
intval($menu_id),
intval(local_channel())
);
}
}
$ret['success'] = true;
}
$x = $ret;
}
else {
$arr['uid'] = local_channel();
$arr['aid'] = $channel['channel_account_id'];
$arr['title'] = $j['title'];
$arr['body'] = $j['body'];
$arr['term'] = $j['term'];
$arr['layout_mid'] = $j['layout_mid'];
$arr['created'] = datetime_convert('UTC','UTC', $j['created']);
$arr['edited'] = datetime_convert('UTC','UTC',$j['edited']);
$arr['owner_xchan'] = get_observer_hash();
$arr['author_xchan'] = (($j['author_xchan']) ? $j['author_xchan'] : get_observer_hash());
$arr['mimetype'] = (($j['mimetype']) ? $j['mimetype'] : 'text/bbcode');
if(! $j['mid'])
$j['mid'] = item_message_id();
$arr['mid'] = $arr['parent_mid'] = $j['mid'];
if($j['pagetitle']) {
require_once('library/urlify/URLify.php');
$pagetitle = strtolower(\URLify::transliterate($j['pagetitle']));
}
// Verify ability to use html or php!!!
$execflag = false;
if($arr['mimetype'] === 'application/x-php') {
$z = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1",
intval(local_channel())
);
if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) {
$execflag = true;
}
}
$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())
);
if($z && $i) {
$remote_id = $z[0]['id'];
$arr['id'] = $i[0]['id'];
// don't update if it has the same timestamp as the original
if($arr['edited'] > $i[0]['edited'])
$x = item_store_update($arr,$execflag);
}
else {
if(($i) && (intval($i[0]['item_deleted']))) {
// was partially deleted already, finish it off
q("delete from item where mid = '%s' and uid = %d",
dbesc($arr['mid']),
intval(local_channel())
);
}
$x = item_store($arr,$execflag);
}
if($x['success']) {
$item_id = $x['item_id'];
update_remote_id($channel,$item_id,$arr['item_type'],$pagetitle,$namespace,$remote_id,$arr['mid']);
}
}
if($x['success']) {
$ret['success'] = true;
info( sprintf( t('%s element installed'), $installed_type));
}
else {
notice( sprintf( t('%s element installation failed'), $installed_type));
}
//??? should perhaps return ret?
json_return_and_die(true);
}
}

553
Zotlabs/Module/Import.php Normal file
View File

@@ -0,0 +1,553 @@
<?php
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/import.php');
class Import extends \Zotlabs\Web\Controller {
function import_account($account_id) {
if(! $account_id){
logger("import_account: No account ID supplied");
return;
}
$max_identities = account_service_class_fetch($account_id,'total_identities');
$max_friends = account_service_class_fetch($account_id,'total_channels');
$max_feeds = account_service_class_fetch($account_id,'total_feeds');
if($max_identities !== false) {
$r = q("select channel_id from channel where channel_account_id = %d",
intval($account_id)
);
if($r && count($r) > $max_identities) {
notice( sprintf( t('Your service plan only allows %d channels.'), $max_identities) . EOL);
return;
}
}
$data = null;
$seize = ((x($_REQUEST,'make_primary')) ? intval($_REQUEST['make_primary']) : 0);
$import_posts = ((x($_REQUEST,'import_posts')) ? intval($_REQUEST['import_posts']) : 0);
$src = $_FILES['filename']['tmp_name'];
$filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type'];
$completed = ((array_key_exists('import_step',$_SESSION)) ? intval($_SESSION['import_step']) : 0);
if($completed)
logger('saved import step: ' . $_SESSION['import_step']);
if($src) {
// This is OS specific and could also fail if your tmpdir isn't very large
// mostly used for Diaspora which exports gzipped files.
if(strpos($filename,'.gz')){
@rename($src,$src . '.gz');
@system('gunzip ' . escapeshellarg($src . '.gz'));
}
if($filesize) {
$data = @file_get_contents($src);
}
unlink($src);
}
if(! $src) {
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
if(! $old_address) {
logger('mod_import: nothing to import.');
notice( t('Nothing to import.') . EOL);
return;
}
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
$channelname = substr($old_address,0,strpos($old_address,'@'));
$servername = substr($old_address,strpos($old_address,'@')+1);
$scheme = 'https://';
$api_path = '/api/red/channel/export/basic?f=&channel=' . $channelname;
if($import_posts)
$api_path .= '&posts=1';
$binary = false;
$redirects = 0;
$opts = array('http_auth' => $email . ':' . $password);
$url = $scheme . $servername . $api_path;
$ret = z_fetch_url($url, $binary, $redirects, $opts);
if(! $ret['success'])
$ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
if($ret['success'])
$data = $ret['body'];
else
notice( t('Unable to download data from old server') . EOL);
}
if(! $data) {
logger('mod_import: empty file.');
notice( t('Imported file is empty.') . EOL);
return;
}
$data = json_decode($data,true);
// logger('import: data: ' . print_r($data,true));
// print_r($data);
if(array_key_exists('user',$data) && array_key_exists('version',$data)) {
require_once('include/Import/import_diaspora.php');
import_diaspora($data);
return;
}
$moving = false;
if(array_key_exists('compatibility',$data) && array_key_exists('database',$data['compatibility'])) {
$v1 = substr($data['compatibility']['database'],-4);
$v2 = substr(DB_UPDATE_VERSION,-4);
if($v2 > $v1) {
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
notice($t);
}
if(array_key_exists('server_role',$data['compatibility']) && $data['compatibility']['server_role'] == 'basic')
$moving = true;
}
if($moving)
$seize = 1;
// import channel
if(array_key_exists('channel',$data)) {
if($completed < 1) {
$channel = import_channel($data['channel'], $account_id, $seize);
}
else {
$r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1",
intval($account_id),
dbesc($channel['channel_guid'])
);
if($r)
$channel = $r[0];
}
if(! $channel) {
logger('mod_import: channel not found. ', print_r($channel,true));
notice( t('Cloned channel not found. Import failed.') . EOL);
return;
}
}
if(! $channel)
$channel = \App::get_channel();
if(! $channel) {
logger('mod_import: channel not found. ', print_r($channel,true));
notice( t('No channel. Import failed.') . EOL);
return;
}
if($completed < 2) {
if(is_array($data['config'])) {
import_config($channel,$data['config']);
}
logger('import step 2');
$_SESSION['import_step'] = 2;
}
if($completed < 3) {
if($data['photo']) {
require_once('include/photo/photo_driver.php');
import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],$account_id,$channel['channel_id']);
}
if(is_array($data['profile']))
import_profiles($channel,$data['profile']);
logger('import step 3');
$_SESSION['import_step'] = 3;
}
if($completed < 4) {
if(is_array($data['hubloc']) && (! $moving)) {
import_hublocs($channel,$data['hubloc'],$seize);
}
logger('import step 4');
$_SESSION['import_step'] = 4;
}
if($completed < 5) {
// create new hubloc for the new channel at this site
$r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_primary,
hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey )
values ( '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s' )",
dbesc($channel['channel_guid']),
dbesc($channel['channel_guid_sig']),
dbesc($channel['channel_hash']),
dbesc($channel['channel_address'] . '@' . \App::get_hostname()),
dbesc('zot'),
intval(($seize) ? 1 : 0),
dbesc(z_root()),
dbesc(base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey']))),
dbesc(\App::get_hostname()),
dbesc(z_root() . '/post'),
dbesc(get_config('system','pubkey'))
);
// reset the original primary hubloc if it is being seized
if($seize) {
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
dbesc($channel['channel_hash']),
dbesc(z_root())
);
}
logger('import step 5');
$_SESSION['import_step'] = 5;
}
if($completed < 6) {
// import xchans and contact photos
if($seize) {
// replace any existing xchan we may have on this site if we're seizing control
$r = q("delete from xchan where xchan_hash = '%s'",
dbesc($channel['channel_hash'])
);
$r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_hidden, xchan_orphan, xchan_censored, xchan_selfcensored, xchan_system, xchan_pubforum, xchan_deleted ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, %d, %d, %d )",
dbesc($channel['channel_hash']),
dbesc($channel['channel_guid']),
dbesc($channel['channel_guid_sig']),
dbesc($channel['channel_pubkey']),
dbesc(z_root() . "/photo/profile/l/" . $channel['channel_id']),
dbesc(z_root() . "/photo/profile/m/" . $channel['channel_id']),
dbesc(z_root() . "/photo/profile/s/" . $channel['channel_id']),
dbesc($channel['channel_address'] . '@' . \App::get_hostname()),
dbesc(z_root() . '/channel/' . $channel['channel_address']),
dbesc(z_root() . '/follow?f=&url=%s'),
dbesc(z_root() . '/poco/' . $channel['channel_address']),
dbesc($channel['channel_name']),
dbesc('zot'),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
0,0,0,0,0,0,0
);
}
logger('import step 6');
$_SESSION['import_step'] = 6;
}
if($completed < 7) {
$xchans = $data['xchan'];
if($xchans) {
foreach($xchans as $xchan) {
$hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
if($xchan['xchan_network'] === 'zot' && $hash !== $xchan['xchan_hash']) {
logger('forged xchan: ' . print_r($xchan,true));
continue;
}
if(! array_key_exists('xchan_hidden',$xchan)) {
$xchan['xchan_hidden'] = (($xchan['xchan_flags'] & 0x0001) ? 1 : 0);
$xchan['xchan_orphan'] = (($xchan['xchan_flags'] & 0x0002) ? 1 : 0);
$xchan['xchan_censored'] = (($xchan['xchan_flags'] & 0x0004) ? 1 : 0);
$xchan['xchan_selfcensored'] = (($xchan['xchan_flags'] & 0x0008) ? 1 : 0);
$xchan['xchan_system'] = (($xchan['xchan_flags'] & 0x0010) ? 1 : 0);
$xchan['xchan_pubforum'] = (($xchan['xchan_flags'] & 0x0020) ? 1 : 0);
$xchan['xchan_deleted'] = (($xchan['xchan_flags'] & 0x1000) ? 1 : 0);
}
$r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
dbesc($xchan['xchan_hash'])
);
if($r)
continue;
dbesc_array($xchan);
$r = dbq("INSERT INTO xchan (`"
. implode("`, `", array_keys($xchan))
. "`) VALUES ('"
. implode("', '", array_values($xchan))
. "')" );
require_once('include/photo/photo_driver.php');
$photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']);
if($photos[4])
$photodate = NULL_DATE;
else
$photodate = $xchan['xchan_photo_date'];
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s'
where xchan_hash = '%s'",
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
dbesc($photos[3]),
dbesc($photodate),
dbesc($xchan['xchan_hash'])
);
}
}
logger('import step 7');
$_SESSION['import_step'] = 7;
}
// FIXME - ensure we have an xchan if somebody is trying to pull a fast one
if($completed < 8) {
$friends = 0;
$feeds = 0;
// import contacts
$abooks = $data['abook'];
if($abooks) {
foreach($abooks as $abook) {
$abconfig = null;
if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
$abconfig = $abook['abconfig'];
unset($abook['abook_id']);
unset($abook['abook_rating']);
unset($abook['abook_rating_text']);
$abook['abook_account'] = $account_id;
$abook['abook_channel'] = $channel['channel_id'];
if(! array_key_exists('abook_blocked',$abook)) {
$abook['abook_blocked'] = (($abook['abook_flags'] & 0x0001 ) ? 1 : 0);
$abook['abook_ignored'] = (($abook['abook_flags'] & 0x0002 ) ? 1 : 0);
$abook['abook_hidden'] = (($abook['abook_flags'] & 0x0004 ) ? 1 : 0);
$abook['abook_archived'] = (($abook['abook_flags'] & 0x0008 ) ? 1 : 0);
$abook['abook_pending'] = (($abook['abook_flags'] & 0x0010 ) ? 1 : 0);
$abook['abook_unconnected'] = (($abook['abook_flags'] & 0x0020 ) ? 1 : 0);
$abook['abook_self'] = (($abook['abook_flags'] & 0x0080 ) ? 1 : 0);
$abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0);
}
if($abook['abook_self']) {
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) {
q("update xchan set xchan_pubforum = 1 where xchan_hash = '%s' ",
dbesc($abook['abook_xchan'])
);
}
}
else {
if($max_friends !== false && $friends > $max_friends)
continue;
if($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds))
continue;
}
dbesc_array($abook);
$r = dbq("INSERT INTO abook (`"
. implode("`, `", array_keys($abook))
. "`) VALUES ('"
. implode("', '", array_values($abook))
. "')" );
$friends ++;
if(intval($abook['abook_feed']))
$feeds ++;
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']);
}
}
}
}
logger('import step 8');
$_SESSION['import_step'] = 8;
}
if($completed < 9) {
$groups = $data['group'];
if($groups) {
$saved = array();
foreach($groups as $group) {
$saved[$group['hash']] = array('old' => $group['id']);
unset($group['id']);
$group['uid'] = $channel['channel_id'];
dbesc_array($group);
$r = dbq("INSERT INTO groups (`"
. implode("`, `", array_keys($group))
. "`) VALUES ('"
. implode("', '", array_values($group))
. "')" );
}
$r = q("select * from `groups` where uid = %d",
intval($channel['channel_id'])
);
if($r) {
foreach($r as $rr) {
$saved[$rr['hash']]['new'] = $rr['id'];
}
}
}
$group_members = $data['group_member'];
if($group_members) {
foreach($group_members as $group_member) {
unset($group_member['id']);
$group_member['uid'] = $channel['channel_id'];
foreach($saved as $x) {
if($x['old'] == $group_member['gid'])
$group_member['gid'] = $x['new'];
}
dbesc_array($group_member);
$r = dbq("INSERT INTO group_member (`"
. implode("`, `", array_keys($group_member))
. "`) VALUES ('"
. implode("', '", array_values($group_member))
. "')" );
}
}
logger('import step 9');
$_SESSION['import_step'] = 9;
}
if(is_array($data['obj']))
import_objs($channel,$data['obj']);
if(is_array($data['likes']))
import_likes($channel,$data['likes']);
if(is_array($data['app']))
import_apps($channel,$data['app']);
if(is_array($data['chatroom']))
import_chatrooms($channel,$data['chatroom']);
if(is_array($data['conv']))
import_conv($channel,$data['conv']);
if(is_array($data['mail']))
import_mail($channel,$data['mail']);
if(is_array($data['event']))
import_events($channel,$data['event']);
if(is_array($data['event_item']))
import_items($channel,$data['event_item']);
if(is_array($data['menu']))
import_menus($channel,$data['menu']);
$addon = array('channel' => $channel,'data' => $data);
call_hooks('import_channel',$addon);
$saved_notification_flags = notifications_off($channel['channel_id']);
if($import_posts && array_key_exists('item',$data) && $data['item'])
import_items($channel,$data['item']);
notifications_on($channel['channel_id'],$saved_notification_flags);
if(array_key_exists('item_id',$data) && $data['item_id'])
import_item_ids($channel,$data['item_id']);
// FIXME - ensure we have a self entry if somebody is trying to pull a fast one
// send out refresh requests
// notify old server that it may no longer be primary.
proc_run('php','include/notifier.php','location',$channel['channel_id']);
// This will indirectly perform a refresh_all *and* update the directory
proc_run('php', 'include/directory.php', $channel['channel_id']);
notice( t('Import completed.') . EOL);
change_channel($channel['channel_id']);
unset($_SESSION['import_step']);
goaway(z_root() . '/network' );
}
function post() {
$account_id = get_account_id();
if(! $account_id)
return;
$this->import_account($account_id);
}
function get() {
if(! get_account_id()) {
notice( t('You must be logged in to use this feature.'));
return '';
}
$o = replace_macros(get_markup_template('channel_import.tpl'),array(
'$title' => t('Import Channel'),
'$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'),
'$label_filename' => t('File to Upload'),
'$choice' => t('Or provide the old server/hub details'),
'$label_old_address' => t('Your old identity address (xyz@example.com)'),
'$label_old_email' => t('Your old login email address'),
'$label_old_pass' => t('Your old login password'),
'$common' => t('For either option, please choose whether to make this hub your new primary address, or whether your old location should continue this role. You will be able to post from either location, but only one can be marked as the primary location for files, photos, and media.'),
'$label_import_primary' => t('Make this hub my primary location'),
'$label_import_posts' => t('Import existing posts if possible (experimental - limited by available memory'),
'$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'),
'$email' => '',
'$pass' => '',
'$submit' => t('Submit')
));
return $o;
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace Zotlabs\Module;
require_once('include/import.php');
class Import_items extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
$data = null;
$src = $_FILES['filename']['tmp_name'];
$filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type'];
if($src) {
// This is OS specific and could also fail if your tmpdir isn't very large
// mostly used for Diaspora which exports gzipped files.
if(strpos($filename,'.gz')){
@rename($src,$src . '.gz');
@system('gunzip ' . escapeshellarg($src . '.gz'));
}
if($filesize) {
$data = @file_get_contents($src);
}
unlink($src);
}
if(! $src) {
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
if(! $old_address) {
logger('mod_import: nothing to import.');
notice( t('Nothing to import.') . EOL);
return;
}
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
$year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : '');
$channelname = substr($old_address,0,strpos($old_address,'@'));
$servername = substr($old_address,strpos($old_address,'@')+1);
$scheme = 'https://';
$api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year);
$binary = false;
$redirects = 0;
$opts = array('http_auth' => $email . ':' . $password);
$url = $scheme . $servername . $api_path;
$ret = z_fetch_url($url, $binary, $redirects, $opts);
if(! $ret['success'])
$ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
if($ret['success'])
$data = $ret['body'];
else
notice( t('Unable to download data from old server') . EOL);
}
if(! $data) {
logger('mod_import: empty file.');
notice( t('Imported file is empty.') . EOL);
return;
}
$data = json_decode($data,true);
// logger('import: data: ' . print_r($data,true));
// print_r($data);
if(array_key_exists('compatibility',$data) && array_key_exists('database',$data['compatibility'])) {
$v1 = substr($data['compatibility']['database'],-4);
$v2 = substr(DB_UPDATE_VERSION,-4);
if($v2 > $v1) {
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
notice($t);
}
}
$channel = \App::get_channel();
if(array_key_exists('item',$data) && $data['item']) {
import_items($channel,$data['item']);
}
if(array_key_exists('item_id',$data) && $data['item_id']) {
import_item_ids($channel,$data['item_id']);
}
info( t('Import completed') . EOL);
return;
}
function get() {
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return login();
}
$o = replace_macros(get_markup_template('item_import.tpl'),array(
'$title' => t('Import Items'),
'$desc' => t('Use this form to import existing posts and content from an export file.'),
'$label_filename' => t('File to Upload'),
'$submit' => t('Submit')
));
return $o;
}
}

152
Zotlabs/Module/Invite.php Normal file
View File

@@ -0,0 +1,152 @@
<?php
namespace Zotlabs\Module;
/**
* module: invite.php
*
* send email invitations to join social network
*
*/
class Invite extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
check_form_security_token_redirectOnErr('/', 'send_invite');
$max_invites = intval(get_config('system','max_invites'));
if(! $max_invites)
$max_invites = 50;
$current_invites = intval(get_pconfig(local_channel(),'system','sent_invites'));
if($current_invites > $max_invites) {
notice( t('Total invitation limit exceeded.') . EOL);
return;
};
$recips = ((x($_POST,'recipients')) ? explode("\n",$_POST['recipients']) : array());
$message = ((x($_POST,'message')) ? notags(trim($_POST['message'])) : '');
$total = 0;
if(get_config('system','invitation_only')) {
$invonly = true;
$x = get_pconfig(local_channel(),'system','invites_remaining');
if((! $x) && (! is_site_admin()))
return;
}
foreach($recips as $recip) {
$recip = trim($recip);
if(! $recip)
continue;
if(! valid_email($recip)) {
notice( sprintf( t('%s : Not a valid email address.'), $recip) . EOL);
continue;
}
else
$nmessage = $message;
$account = \App::get_account();
$res = mail($recip, sprintf( t('Please join us on $Projectname'), \App::$config['sitename']),
$nmessage,
"From: " . $account['account_email'] . "\n"
. 'Content-type: text/plain; charset=UTF-8' . "\n"
. 'Content-transfer-encoding: 8bit' );
if($res) {
$total ++;
$current_invites ++;
set_pconfig(local_channel(),'system','sent_invites',$current_invites);
if($current_invites > $max_invites) {
notice( t('Invitation limit exceeded. Please contact your site administrator.') . EOL);
return;
}
}
else {
notice( sprintf( t('%s : Message delivery failed.'), $recip) . EOL);
}
}
notice( sprintf( tt("%d message sent.", "%d messages sent.", $total) , $total) . EOL);
return;
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$tpl = get_markup_template('invite.tpl');
$invonly = false;
if(get_config('system','invitation_only')) {
$invonly = true;
$x = get_pconfig(local_channel(),'system','invites_remaining');
if((! $x) && (! is_site_admin())) {
notice( t('You have no more invitations available') . EOL);
return '';
}
}
if($invonly && ($x || is_site_admin())) {
$invite_code = autoname(8) . rand(1000,9999);
$nmessage = str_replace('$invite_code',$invite_code,$message);
$r = q("INSERT INTO `register` (`hash`,`created`) VALUES ('%s', '%s') ",
dbesc($invite_code),
dbesc(datetime_convert())
);
if(! is_site_admin()) {
$x --;
if($x >= 0)
set_pconfig(local_channel(),'system','invites_remaining',$x);
else
return;
}
}
$ob = \App::get_observer();
if(! $ob)
return $o;
$channel = \App::get_channel();
$o = replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("send_invite"),
'$invite' => t('Send invitations'),
'$addr_text' => t('Enter email addresses, one per line:'),
'$msg_text' => t('Your message:'),
'$default_message' => t('Please join my community on $Projectname.') . "\r\n" . "\r\n"
. $linktxt
. (($invonly) ? "\r\n" . "\r\n" . t('You will need to supply this invitation code:') . " " . $invite_code . "\r\n" . "\r\n" : '')
. t('1. Register at any $Projectname location (they are all inter-connected)')
. "\r\n" . "\r\n" . z_root() . '/register'
. "\r\n" . "\r\n" . t('2. Enter my $Projectname network address into the site searchbar.')
. "\r\n" . "\r\n" . $ob['xchan_addr'] . ' (' . t('or visit') . " " . z_root() . '/channel/' . $channel['channel_address'] . ')'
. "\r\n" . "\r\n"
. t('3. Click [Connect]')
. "\r\n" . "\r\n" ,
'$submit' => t('Submit')
));
return $o;
}
}

1265
Zotlabs/Module/Item.php Normal file

File diff suppressed because it is too large Load Diff

12
Zotlabs/Module/Lang.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
namespace Zotlabs\Module;
class Lang extends \Zotlabs\Web\Controller {
function get() {
return lang_selector();
}
}

202
Zotlabs/Module/Layouts.php Normal file
View File

@@ -0,0 +1,202 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
class Layouts extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$_SESSION['return_url'] = \App::$query_string;
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
// Block design features from visitors
if((! $uid) || ($uid != $owner)) {
notice( t('Permission denied.') . EOL);
return;
}
// Get the observer, check their permissions
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
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.
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",
intval($owner),
dbesc(argv(3))
);
if($r) {
header('Content-type: application/x-hubzilla-layout');
header('Content-disposition: attachment; filename="' . $r[0]['sid'] . '.pdl"');
echo json_encode($r);
killme();
}
}
// Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages
// Nickname is set to the observers xchan, and profile_uid to the owners.
// This lets you post pages at other people's channels.
$x = array(
'webpage' => ITEM_TYPE_PDL,
'is_owner' => true,
'nickname' => \App::$profile['channel_address'],
'showacl' => false,
'hide_voting' => true,
'hide_future' => true,
'hide_expire' => true,
'hide_location' => true,
'hide_weblink' => true,
'hide_attach' => true,
'hide_preview' => true,
'ptlabel' => t('Layout Name'),
'profile_uid' => intval($owner),
'expanded' => true,
'placeholdertitle' => t('Layout Description (Optional)'),
'novoting' => true,
'bbco_autocomplete' => 'comanche'
);
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
if($_REQUEST['pagetitle'])
$x['pagetitle'] = $_REQUEST['pagetitle'];
$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",
intval($owner),
intval(ITEM_TYPE_PDL)
);
$pages = null;
if($r) {
$pages = array();
foreach($r as $rr) {
$element_arr = array(
'type' => 'layout',
'title' => $rr['title'],
'body' => $rr['body'],
'created' => $rr['created'],
'edited' => $rr['edited'],
'mimetype' => $rr['mimetype'],
'pagetitle' => $rr['sid'],
'mid' => $rr['mid']
);
$pages[$rr['iid']][] = array(
'url' => $rr['iid'],
'title' => $rr['sid'],
'descr' => $rr['title'],
'mid' => $rr['mid'],
'created' => $rr['created'],
'edited' => $rr['edited'],
'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]'
);
}
}
//Build the base URL for edit links
$url = z_root() . '/editlayout/' . $which;
$o .= replace_macros(get_markup_template('layoutlist.tpl'), array(
'$title' => t('Layouts'),
'$create' => t('Create'),
'$help' => array('text' => t('Help'), 'url' => 'help/comanche', 'title' => t('Comanche page description language help')),
'$editor' => $editor,
'$baseurl' => $url,
'$name' => t('Layout Name'),
'$descr' => t('Layout Description'),
'$created' => t('Created'),
'$edited' => t('Edited'),
'$edit' => t('Edit'),
'$share' => t('Share'),
'$download' => t('Download PDL file'),
'$pages' => $pages,
'$channel' => $which,
'$view' => t('View'),
));
return $o;
}
}

547
Zotlabs/Module/Like.php Normal file
View File

@@ -0,0 +1,547 @@
<?php
namespace Zotlabs\Module;
require_once('include/security.php');
require_once('include/bbcode.php');
require_once('include/items.php');
class Like extends \Zotlabs\Web\Controller {
function get() {
$o = '';
$observer = \App::get_observer();
$interactive = $_REQUEST['interactive'];
if($interactive) {
$o .= '<h1>' . t('Like/Dislike') . '</h1>';
$o .= EOL . EOL;
if(! $observer) {
$_SESSION['return_url'] = \App::$query_string;
$o .= t('This action is restricted to members.') . EOL;
$o .= t('Please <a href="rmagic">login with your $Projectname ID</a> or <a href="register">register as a new $Projectname member</a> to continue.') . EOL;
return $o;
}
}
$verb = notags(trim($_GET['verb']));
if(! $verb)
$verb = 'like';
switch($verb) {
case 'like':
case 'unlike':
$activity = ACTIVITY_LIKE;
break;
case 'dislike':
case 'undislike':
$activity = ACTIVITY_DISLIKE;
break;
case 'agree':
case 'unagree':
$activity = ACTIVITY_AGREE;
break;
case 'disagree':
case 'undisagree':
$activity = ACTIVITY_DISAGREE;
break;
case 'abstain':
case 'unabstain':
$activity = ACTIVITY_ABSTAIN;
break;
case 'attendyes':
case 'unattendyes':
$activity = ACTIVITY_ATTEND;
break;
case 'attendno':
case 'unattendno':
$activity = ACTIVITY_ATTENDNO;
break;
case 'attendmaybe':
case 'unattendmaybe':
$activity = ACTIVITY_ATTENDMAYBE;
break;
default:
return;
break;
}
$extended_like = false;
$object = $target = null;
$post_type = '';
$objtype = '';
if(argc() == 3) {
if(! $observer)
killme();
$extended_like = true;
$obj_type = argv(1);
$obj_id = argv(2);
$public = true;
if($obj_type == 'profile') {
$r = q("select * from profile where profile_guid = '%s' limit 1",
dbesc(argv(2))
);
if(! $r)
killme();
$owner_uid = $r[0]['uid'];
if($r[0]['is_default'])
$public = true;
if(! $public) {
$d = q("select abook_xchan from abook where abook_profile = '%s' and abook_channel = %d",
dbesc($r[0]['profile_guid']),
intval($owner_uid)
);
if(! $d) {
// forgery - illegal
if($interactive) {
notice( t('Invalid request.') . EOL);
return $o;
}
killme();
}
// $d now contains a list of those who can see this profile - only send the status notification
// to them.
$allow_cid = $allow_gid = $deny_cid = $deny_gid = '';
foreach($d as $dd) {
$allow_cid .= '<' . $dd['abook_xchan'] . '>';
}
}
$post_type = t('channel');
$objtype = ACTIVITY_OBJ_PROFILE;
$profile = $r[0];
}
elseif($obj_type == 'thing') {
$r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1",
intval(TERM_OBJ_THING),
dbesc(argv(2))
);
if(! $r) {
if($interactive) {
notice( t('Invalid request.') . EOL);
return $o;
}
killme();
}
$owner_uid = $r[0]['obj_channel'];
$allow_cid = $r[0]['allow_cid'];
$allow_gid = $r[0]['allow_gid'];
$deny_cid = $r[0]['deny_cid'];
$deny_gid = $r[0]['deny_gid'];
if($allow_cid || $allow_gid || $deny_cid || $deny_gid)
$public = false;
$post_type = t('thing');
$objtype = ACTIVITY_OBJ_PROFILE;
$tgttype = ACTIVITY_OBJ_THING;
$links = array();
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
'href' => z_root() . '/thing/' . $r[0]['obj_obj']);
if($r[0]['imgurl'])
$links[] = array('rel' => 'photo', 'href' => $r[0]['obj_imgurl']);
$target = json_encode(array(
'type' => $tgttype,
'title' => $r[0]['obj_term'],
'id' => z_root() . '/thing/' . $r[0]['obj_obj'],
'link' => $links
));
$plink = '[zrl=' . z_root() . '/thing/' . $r[0]['obj_obj'] . ']' . $r[0]['obj_term'] . '[/zrl]';
}
if(! ($owner_uid && $r)) {
if($interactive) {
notice( t('Invalid request.') . EOL);
return $o;
}
killme();
}
// The resultant activity is going to be a wall-to-wall post, so make sure this is allowed
$perms = get_all_perms($owner_uid,$observer['xchan_hash']);
if(! ($perms['post_like'] && $perms['view_profile'])) {
if($interactive) {
notice( t('Permission denied.') . EOL);
return $o;
}
killme();
}
$ch = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
intval($owner_uid)
);
if(! $ch) {
if($interactive) {
notice( t('Channel unavailable.') . EOL);
return $o;
}
killme();
}
if(! $plink)
$plink = '[zrl=' . z_root() . '/profile/' . $ch[0]['channel_address'] . ']' . $post_type . '[/zrl]';
$links = array();
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
'href' => z_root() . '/profile/' . $ch[0]['channel_address']);
$links[] = array('rel' => 'photo', 'type' => $ch[0]['xchan_photo_mimetype'],
'href' => $ch[0]['xchan_photo_l']);
$object = json_encode(array(
'type' => ACTIVITY_OBJ_PROFILE,
'title' => $ch[0]['channel_name'],
'id' => $ch[0]['xchan_url'] . '/' . $ch[0]['xchan_hash'],
'link' => $links
));
// second like of the same thing is "undo" for the first like
$z = q("select * from likes where channel_id = %d and liker = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' limit 1",
intval($ch[0]['channel_id']),
dbesc($observer['xchan_hash']),
dbesc($activity),
dbesc(($tgttype)?$tgttype:$objtype),
dbesc($obj_id)
);
if($z) {
$z[0]['deleted'] = 1;
build_sync_packet($ch[0]['channel_id'],array('likes' => $z));
q("delete from likes where id = %d limit 1",
intval($z[0]['id'])
);
if($z[0]['i_mid']) {
$r = q("select id from item where mid = '%s' and uid = %d limit 1",
dbesc($z[0]['i_mid']),
intval($ch[0]['channel_id'])
);
if($r)
drop_item($r[0]['id'],false);
if($interactive) {
notice( t('Previous action reversed.') . EOL);
return $o;
}
}
killme();
}
}
else {
// this is used to like an item or comment
$item_id = ((argc() == 2) ? notags(trim(argv(1))) : 0);
logger('like: verb ' . $verb . ' item ' . $item_id, LOGGER_DEBUG);
// get the item. Allow linked photos (which are normally hidden) to be liked
$r = q("SELECT * FROM item WHERE id = %d
and item_type = 0 and item_deleted = 0 and item_unpublished = 0
and item_delayed = 0 and item_pending_remove = 0 and item_blocked = 0 LIMIT 1",
intval($item_id)
);
if(! $item_id || (! $r)) {
logger('like: no item ' . $item_id);
killme();
}
$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'))) {
notice( t('Permission denied') . EOL);
killme();
}
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['owner_xchan'])
);
if($r)
$thread_owner = $r[0];
else
killme();
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['author_xchan'])
);
if($r)
$item_author = $r[0];
else
killme();
$verbs = " '".dbesc($activity)."' ";
$multi_undo = false;
// event participation and consensus items are essentially radio toggles. If you make a subsequent choice,
// we need to eradicate your first choice.
if($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
$verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
$multi_undo = 1;
}
if($activity === ACTIVITY_AGREE || $activity === ACTIVITY_DISAGREE || $activity === ACTIVITY_ABSTAIN) {
$verbs = " '" . dbesc(ACTIVITY_AGREE) . "','" . dbesc(ACTIVITY_DISAGREE) . "','" . dbesc(ACTIVITY_ABSTAIN) . "' ";
$multi_undo = true;
}
$item_normal = item_normal();
$r = q("SELECT id, parent, uid, verb FROM item WHERE verb in ( $verbs ) $item_normal
AND author_xchan = '%s' AND thr_parent = '%s' and uid = %d ",
dbesc($observer['xchan_hash']),
dbesc($item['mid']),
intval($owner_uid)
);
if($r) {
// already liked it. Drop that item.
require_once('include/items.php');
foreach($r as $rr) {
drop_item($rr['id'],false,DROPITEM_PHASE1);
// set the changed timestamp on the parent so we'll see the update without a page reload
$z = q("update item set changed = '%s' where id = %d and uid = %d",
dbesc(datetime_convert()),
intval($rr['parent']),
intval($rr['uid'])
);
// Prior activity was a duplicate of the one we're submitting, just undo it;
// don't fall through and create another
if(activity_match($rr['verb'],$activity))
$multi_undo = false;
// 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']);
}
if($interactive)
return;
if(! $multi_undo)
killme();
}
}
$mid = item_message_id();
$arr = array();
if($extended_like) {
$arr['item_thread_top'] = 1;
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
}
else {
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
if($item['obj_type'] === ACTIVITY_OBJ_EVENT)
$post_type = t('event');
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
$body = $item['body'];
$object = json_encode(array(
'type' => $objtype,
'id' => $item['mid'],
'parent' => (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']),
'link' => $links,
'title' => $item['title'],
'content' => $item['body'],
'created' => $item['created'],
'edited' => $item['edited'],
'author' => array(
'name' => $item_author['xchan_name'],
'address' => $item_author['xchan_addr'],
'guid' => $item_author['xchan_guid'],
'guid_sig' => $item_author['xchan_guid_sig'],
'link' => array(
array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']),
array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])),
),
));
if(! intval($item['item_thread_top']))
$post_type = 'comment';
$arr['item_origin'] = 1;
$arr['item_notshown'] = 1;
if(intval($item['item_wall']))
$arr['item_wall'] = 1;
// if this was a linked photo and was hidden, unhide it.
if(intval($item['item_hidden'])) {
$r = q("update item set item_hidden = 0 where id = %d",
intval($item['id'])
);
}
}
if($verb === 'like')
$bodyverb = t('%1$s likes %2$s\'s %3$s');
if($verb === 'dislike')
$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
if($verb === 'agree')
$bodyverb = t('%1$s agrees with %2$s\'s %3$s');
if($verb === 'disagree')
$bodyverb = t('%1$s doesn\'t agree with %2$s\'s %3$s');
if($verb === 'abstain')
$bodyverb = t('%1$s abstains from a decision on %2$s\'s %3$s');
if($verb === 'attendyes')
$bodyverb = t('%1$s is attending %2$s\'s %3$s');
if($verb === 'attendno')
$bodyverb = t('%1$s is not attending %2$s\'s %3$s');
if($verb === 'attendmaybe')
$bodyverb = t('%1$s may attend %2$s\'s %3$s');
if(! isset($bodyverb))
killme();
if($extended_like) {
$ulink = '[zrl=' . $ch[0]['xchan_url'] . ']' . $ch[0]['xchan_name'] . '[/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
$private = (($public) ? 0 : 1);
}
else {
$arr['parent'] = $item['id'];
$arr['thr_parent'] = $item['mid'];
$ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
$plink = '[zrl=' . z_root() . '/display/' . $item['mid'] . ']' . $post_type . '[/zrl]';
$allow_cid = $item['allow_cid'];
$allow_gid = $item['allow_gid'];
$deny_cid = $item['deny_cid'];
$deny_gid = $item['deny_gid'];
$private = $item['private'];
}
$arr['mid'] = $mid;
$arr['aid'] = (($extended_like) ? $ch[0]['channel_account_id'] : $owner_aid);
$arr['uid'] = $owner_uid;
$arr['item_flags'] = $item_flags;
$arr['item_wall'] = $item_wall;
$arr['parent_mid'] = (($extended_like) ? $mid : $item['mid']);
$arr['owner_xchan'] = (($extended_like) ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash']);
$arr['author_xchan'] = $observer['xchan_hash'];
$arr['body'] = sprintf( $bodyverb, $alink, $ulink, $plink );
if($obj_type === 'thing' && $r[0]['imgurl']) {
$arr['body'] .= "\n\n[zmg=80x80]" . $r[0]['imgurl'] . '[/zmg]';
}
if($obj_type === 'profile') {
if($public) {
$arr['body'] .= "\n\n" . '[embed]' . z_root() . '/profile/' . $ch[0]['channel_address'] . '[/embed]';
}
else
$arr['body'] .= "\n\n[zmg=80x80]" . $profile['thumb'] . '[/zmg]';
}
$arr['verb'] = $activity;
$arr['obj_type'] = $objtype;
$arr['object'] = $object;
if($target) {
$arr['tgt_type'] = $tgttype;
$arr['target'] = $target;
}
$arr['allow_cid'] = $allow_cid;
$arr['allow_gid'] = $allow_gid;
$arr['deny_cid'] = $deny_cid;
$arr['deny_gid'] = $deny_gid;
$arr['item_private'] = $private;
$post = item_store($arr);
$post_id = $post['item_id'];
$arr['id'] = $post_id;
call_hooks('post_local_end', $arr);
if($extended_like) {
$r = q("insert into likes (channel_id,liker,likee,iid,i_mid,verb,target_type,target_id,target) values (%d,'%s','%s',%d,'%s','%s','%s','%s','%s')",
intval($ch[0]['channel_id']),
dbesc($observer['xchan_hash']),
dbesc($ch[0]['channel_hash']),
intval($post_id),
dbesc($mid),
dbesc($activity),
dbesc(($tgttype)? $tgttype : $objtype),
dbesc($obj_id),
dbesc(($target) ? $target : $object)
);
$r = q("select * from likes where liker = '%s' and likee = '%s' and i_mid = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' ",
dbesc($observer['xchan_hash']),
dbesc($ch[0]['channel_hash']),
dbesc($mid),
dbesc($activity),
dbesc(($tgttype)? $tgttype : $objtype),
dbesc($obj_id)
);
if($r)
build_sync_packet($ch[0]['channel_id'],array('likes' => $r));
}
proc_run('php',"include/notifier.php","like","$post_id");
if($interactive) {
notice( t('Action completed.') . EOL);
$o .= t('Thank you.');
return $o;
}
killme();
}
}

381
Zotlabs/Module/Linkinfo.php Normal file
View File

@@ -0,0 +1,381 @@
<?php
namespace Zotlabs\Module;
class Linkinfo extends \Zotlabs\Web\Controller {
function get() {
logger('linkinfo: ' . print_r($_REQUEST,true));
$text = null;
$str_tags = '';
$br = "\n";
if(x($_GET,'binurl'))
$url = trim(hex2bin($_GET['binurl']));
else
$url = trim($_GET['url']);
$url = strip_zids($url);
if((substr($url,0,1) != '/') && (substr($url,0,4) != 'http'))
$url = 'http://' . $url;
if($_GET['title'])
$title = strip_tags(trim($_GET['title']));
if($_GET['description'])
$text = strip_tags(trim($_GET['description']));
if($_GET['tags']) {
$arr_tags = str_getcsv($_GET['tags']);
if(count($arr_tags)) {
array_walk($arr_tags,'self::arr_add_hashes');
$str_tags = $br . implode(' ',$arr_tags) . $br;
}
}
logger('linkinfo: ' . $url);
$result = z_fetch_url($url,false,0,array('novalidate' => true, 'nobody' => true));
if($result['success']) {
$hdrs=array();
$h = explode("\n",$result['header']);
foreach ($h as $l) {
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
$hdrs[$k] = $v;
}
if (array_key_exists('Content-Type', $hdrs))
$type = $hdrs['Content-Type'];
if($type) {
$zrl = is_matrix_url($url);
if(stripos($type,'image/') !== false) {
if($zrl)
echo $br . '[zmg]' . $url . '[/zmg]' . $br;
else
echo $br . '[img]' . $url . '[/img]' . $br;
killme();
}
if(stripos($type,'video/') !== false) {
if($zrl)
echo $br . '[zvideo]' . $url . '[/zvideo]' . $br;
else
echo $br . '[video]' . $url . '[/video]' . $br;
killme();
}
if(stripos($type,'audio/') !== false) {
if($zrl)
echo $br . '[zaudio]' . $url . '[/zaudio]' . $br;
else
echo $br . '[audio]' . $url . '[/audio]' . $br;
killme();
}
}
}
$template = $br . '#^[url=%s]%s[/url]%s' . $br;
$arr = array('url' => $url, 'text' => '');
call_hooks('parse_link', $arr);
if(strlen($arr['text'])) {
echo $arr['text'];
killme();
}
$x = oembed_process($url);
if($x) {
echo $x;
killme();
}
if($url && $title && $text) {
$text = $br . '[quote]' . trim($text) . '[/quote]' . $br;
$title = str_replace(array("\r","\n"),array('',''),$title);
$result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
logger('linkinfo (unparsed): returns: ' . $result);
echo $result;
killme();
}
$siteinfo = self::parseurl_getsiteinfo($url);
// If this is a Red site, use zrl rather than url so they get zids sent to them by default
if( x($siteinfo,'generator') && (strpos($siteinfo['generator'], \Zotlabs\Project\System::get_platform_name() . ' ') === 0))
$template = str_replace('url','zrl',$template);
if($siteinfo["title"] == "") {
echo sprintf($template,$url,$url,'') . $str_tags;
killme();
} else {
$text = $siteinfo["text"];
$title = $siteinfo["title"];
}
$image = "";
if(sizeof($siteinfo["images"]) > 0){
/* Execute below code only if image is present in siteinfo */
$total_images = 0;
$max_images = get_config('system','max_bookmark_images');
if($max_images === false)
$max_images = 2;
else
$max_images = intval($max_images);
foreach ($siteinfo["images"] as $imagedata) {
if ($url) {
$image .= sprintf('[url=%s]', $url);
}
$image .= '[img='.$imagedata["width"].'x'.$imagedata["height"].']'.$imagedata["src"].'[/img]';
if ($url) {
$image .= '[/url]';
}
$image .= "\n";
$total_images ++;
if($max_images && $max_images >= $total_images)
break;
}
}
if(strlen($text)) {
$text = $br.'[quote]'.trim($text).'[/quote]'.$br ;
}
if($image) {
$text = $br.$br.$image.$text;
}
$title = str_replace(array("\r","\n"),array('',''),$title);
$result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
logger('linkinfo: returns: ' . $result, LOGGER_DEBUG);
echo trim($result);
killme();
}
public static function deletexnode(&$doc, $node) {
$xpath = new \DomXPath($doc);
$list = $xpath->query("//".$node);
foreach ($list as $child)
$child->parentNode->removeChild($child);
}
public static function completeurl($url, $scheme) {
$urlarr = parse_url($url);
if (isset($urlarr["scheme"]))
return($url);
$schemearr = parse_url($scheme);
$complete = $schemearr["scheme"]."://".$schemearr["host"];
if ($schemearr["port"] != "")
$complete .= ":".$schemearr["port"];
if(strpos($urlarr['path'],'/') !== 0)
$complete .= '/';
$complete .= $urlarr["path"];
if ($urlarr["query"] != "")
$complete .= "?".$urlarr["query"];
if ($urlarr["fragment"] != "")
$complete .= "#".$urlarr["fragment"];
return($complete);
}
public static function parseurl_getsiteinfo($url) {
$siteinfo = array();
$result = z_fetch_url($url,false,0,array('novalidate' => true));
if(! $result['success'])
return $siteinfo;
$header = $result['header'];
$body = $result['body'];
$body = mb_convert_encoding($body, 'UTF-8', 'UTF-8');
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
$doc = new \DOMDocument();
@$doc->loadHTML($body);
self::deletexnode($doc, 'style');
self::deletexnode($doc, 'script');
self::deletexnode($doc, 'option');
self::deletexnode($doc, 'h1');
self::deletexnode($doc, 'h2');
self::deletexnode($doc, 'h3');
self::deletexnode($doc, 'h4');
self::deletexnode($doc, 'h5');
self::deletexnode($doc, 'h6');
self::deletexnode($doc, 'ol');
self::deletexnode($doc, 'ul');
$xpath = new \DomXPath($doc);
//$list = $xpath->query("head/title");
$list = $xpath->query("//title");
foreach ($list as $node)
$siteinfo["title"] = html_entity_decode($node->nodeValue, ENT_QUOTES, "UTF-8");
//$list = $xpath->query("head/meta[@name]");
$list = $xpath->query("//meta[@name]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
switch (strtolower($attr["name"])) {
case 'generator':
$siteinfo['generator'] = $attr['content'];
break;
case "fulltitle":
$siteinfo["title"] = $attr["content"];
break;
case "description":
$siteinfo["text"] = $attr["content"];
break;
case "dc.title":
$siteinfo["title"] = $attr["content"];
break;
case "dc.description":
$siteinfo["text"] = $attr["content"];
break;
}
}
//$list = $xpath->query("head/meta[@property]");
$list = $xpath->query("//meta[@property]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
switch (strtolower($attr["property"])) {
case "og:image":
$siteinfo["image"] = $attr["content"];
break;
case "og:title":
$siteinfo["title"] = $attr["content"];
break;
case "og:description":
$siteinfo["text"] = $attr["content"];
break;
}
}
if ($siteinfo["image"] == "") {
$list = $xpath->query("//img[@src]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$src = self::completeurl($attr["src"], $url);
$photodata = @getimagesize($src);
if (($photodata) && ($photodata[0] > 150) and ($photodata[1] > 150)) {
if ($photodata[0] > 300) {
$photodata[1] = round($photodata[1] * (300 / $photodata[0]));
$photodata[0] = 300;
}
if ($photodata[1] > 300) {
$photodata[0] = round($photodata[0] * (300 / $photodata[1]));
$photodata[1] = 300;
}
$siteinfo["images"][] = array("src"=>$src,
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
}
} else {
$src = self::completeurl($siteinfo["image"], $url);
unset($siteinfo["image"]);
$photodata = @getimagesize($src);
if (($photodata) && ($photodata[0] > 10) and ($photodata[1] > 10))
$siteinfo["images"][] = array("src"=>$src,
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
if ($siteinfo["text"] == "") {
$text = "";
$list = $xpath->query("//div[@class='article']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
if ($text == "") {
$list = $xpath->query("//div[@class='content']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
// If none text was found then take the paragraph content
if ($text == "") {
$list = $xpath->query("//p");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
if ($text != "") {
$text = trim(str_replace(array("\n", "\r"), array(" ", " "), $text));
while (strpos($text, " "))
$text = trim(str_replace(" ", " ", $text));
$siteinfo["text"] = html_entity_decode(substr($text,0,350), ENT_QUOTES, "UTF-8").'...';
}
}
return($siteinfo);
}
private static function arr_add_hashes(&$item,$k) {
$item = '#' . $item;
}
}

121
Zotlabs/Module/Lockview.php Normal file
View File

@@ -0,0 +1,121 @@
<?php
namespace Zotlabs\Module;
class Lockview extends \Zotlabs\Web\Controller {
function get() {
$type = ((argc() > 1) ? argv(1) : 0);
if (is_numeric($type)) {
$item_id = intval($type);
$type='item';
} else {
$item_id = ((argc() > 2) ? intval(argv(2)) : 0);
}
if(! $item_id)
killme();
if (!in_array($type, array('item','photo','event', 'menu_item', 'chatroom')))
killme();
//we have different naming in in menu_item table and chatroom table
switch($type) {
case 'menu_item':
$id = 'mitem_id';
break;
case 'chatroom':
$id = 'cr_id';
break;
default:
$id = 'id';
break;
}
$r = q("SELECT * FROM %s WHERE $id = %d LIMIT 1",
dbesc($type),
intval($item_id)
);
if(! $r)
killme();
$item = $r[0];
//we have different naming in in menu_item table and chatroom table
switch($type) {
case 'menu_item':
$uid = $item['mitem_channel_id'];
break;
case 'chatroom':
$uid = $item['cr_uid'];
break;
default:
$uid = $item['uid'];
break;
}
if($uid != local_channel()) {
echo '<li>' . t('Remote privacy information not available.') . '</li>';
killme();
}
if(($item['item_private'] == 1) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
&& (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) {
// if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any
// specific recipients, we're the recipient of a post with "bcc" or targeted recipients; so we'll just show it
// as unknown specific recipients. The sender will have the visibility list and will fall through to the
// next section.
echo '<li>' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</li>';
killme();
}
$allowed_users = expand_acl($item['allow_cid']);
$allowed_groups = expand_acl($item['allow_gid']);
$deny_users = expand_acl($item['deny_cid']);
$deny_groups = expand_acl($item['deny_gid']);
$o = '<li>' . t('Visible to:') . '</li>';
$l = array();
stringify_array_elms($allowed_groups,true);
stringify_array_elms($allowed_users,true);
stringify_array_elms($deny_groups,true);
stringify_array_elms($deny_users,true);
if(count($allowed_groups)) {
$r = q("SELECT name FROM `groups` WHERE hash IN ( " . implode(', ', $allowed_groups) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li><b>' . $rr['name'] . '</b></li>';
}
if(count($allowed_users)) {
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ',$allowed_users) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li>' . $rr['xchan_name'] . '</li>';
}
if(count($deny_groups)) {
$r = q("SELECT name FROM `groups` WHERE hash IN ( " . implode(', ', $deny_groups) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li><b><strike>' . $rr['name'] . '</strike></b></li>';
}
if(count($deny_users)) {
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ', $deny_users) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li><strike>' . $rr['xchan_name'] . '</strike></li>';
}
echo $o . implode($l);
killme();
}
}

132
Zotlabs/Module/Locs.php Normal file
View File

@@ -0,0 +1,132 @@
<?php
namespace Zotlabs\Module; /** @file */
class Locs extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
$channel = \App::get_channel();
if($_REQUEST['primary']) {
$hubloc_id = intval($_REQUEST['primary']);
if($hubloc_id) {
$r = q("select hubloc_id from hubloc where hubloc_id = %d and hubloc_hash = '%s' limit 1",
intval($hubloc_id),
dbesc($channel['channel_hash'])
);
if(! $r) {
notice( t('Location not found.') . EOL);
return;
}
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' ",
dbesc($channel['channel_hash'])
);
$r = q("update hubloc set hubloc_primary = 1 where hubloc_id = %d and hubloc_hash = '%s'",
intval($hubloc_id),
dbesc($channel['channel_hash'])
);
proc_run('php','include/notifier.php','location',$channel['channel_id']);
return;
}
}
if($_REQUEST['drop']) {
$hubloc_id = intval($_REQUEST['drop']);
if($hubloc_id) {
$r = q("select * from hubloc where hubloc_id = %d and hubloc_url != '%s' and hubloc_hash = '%s' limit 1",
intval($hubloc_id),
dbesc(z_root()),
dbesc($channel['channel_hash'])
);
if(! $r) {
notice( t('Location not found.') . EOL);
return;
}
if(intval($r[0]['hubloc_primary'])) {
$x = q("select hubloc_id from hubloc where hubloc_primary = 1 and hubloc_hash = '%s'",
dbesc($channel['channel_hash'])
);
if(! $x) {
notice( t('Location lookup failed.'));
return;
}
if(count($x) == 1) {
notice( t('Please select another location to become primary before removing the primary location.') . EOL);
return;
}
}
$r = q("update hubloc set hubloc_deleted = 1 where hubloc_id = %d and hubloc_hash = '%s'",
intval($hubloc_id),
dbesc($channel['channel_hash'])
);
proc_run('php','include/notifier.php','location',$channel['channel_id']);
return;
}
}
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$channel = \App::get_channel();
if($_REQUEST['sync']) {
proc_run('php','include/notifier.php','location',$channel['channel_id']);
info( t('Syncing locations') . EOL);
goaway(z_root() . '/locs');
}
$r = q("select * from hubloc where hubloc_hash = '%s'",
dbesc($channel['channel_hash'])
);
if(! $r) {
notice( t('No locations found.') . EOL);
return;
}
for($x = 0; $x < count($r); $x ++) {
$r[$x]['primary'] = (intval($r[$x]['hubloc_primary']) ? true : false);
$r[$x]['deleted'] = (intval($r[$x]['hubloc_deleted']) ? true : false);
}
$o = replace_macros(get_markup_template('locmanage.tpl'), array(
'$header' => t('Manage Channel Locations'),
'$loc' => t('Location'),
'$addr' => t('Address'),
'$mkprm' => t('Primary'),
'$drop' => t('Drop'),
'$submit' => t('Submit'),
'$sync' => t('Sync Now'),
'$sync_text' => t('Please wait several minutes between consecutive operations.'),
'$drop_text' => t('When possible, drop a location by logging into that website/hub and removing your channel.'),
'$last_resort' => t('Use this form to drop the location if the hub is no longer operating.'),
'$hubs' => $r
));
return $o;
}
}

13
Zotlabs/Module/Login.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
namespace Zotlabs\Module;
class Login extends \Zotlabs\Web\Controller {
function get() {
if(local_channel())
goaway(z_root());
return login((\App::$config['system']['register_policy'] == REGISTER_CLOSED) ? false : true);
}
}

138
Zotlabs/Module/Lostpass.php Normal file
View File

@@ -0,0 +1,138 @@
<?php
namespace Zotlabs\Module;
class Lostpass extends \Zotlabs\Web\Controller {
function post() {
$loginame = notags(trim($_POST['login-name']));
if(! $loginame)
goaway(z_root());
$r = q("SELECT * FROM account WHERE account_email = '%s' LIMIT 1",
dbesc($loginame)
);
if(! $r) {
notice( t('No valid account found.') . EOL);
goaway(z_root());
}
$aid = $r[0]['account_id'];
$email = $r[0]['account_email'];
$hash = random_string();
$r = q("UPDATE account SET account_reset = '%s' WHERE account_id = %d",
dbesc($hash),
intval($aid)
);
if($r)
info( t('Password reset request issued. Check your email.') . EOL);
$email_tpl = get_intltext_template("lostpass_eml.tpl");
$message = replace_macros($email_tpl, array(
'$sitename' => get_config('system','sitename'),
'$siteurl' => z_root(),
'$username' => sprintf( t('Site Member (%s)'), $email),
'$email' => $email,
'$reset_link' => z_root() . '/lostpass?verify=' . $hash
));
$subject = email_header_encode(sprintf( t('Password reset requested at %s'),get_config('system','sitename')), 'UTF-8');
$res = mail($email, $subject ,
$message,
'From: Administrator@' . $_SERVER['SERVER_NAME'] . "\n"
. 'Content-type: text/plain; charset=UTF-8' . "\n"
. 'Content-transfer-encoding: 8bit' );
goaway(z_root());
}
function get() {
if(x($_GET,'verify')) {
$verify = $_GET['verify'];
$r = q("SELECT * FROM account WHERE account_reset = '%s' LIMIT 1",
dbesc($verify)
);
if(! $r) {
notice( t("Request could not be verified. (You may have previously submitted it.) Password reset failed.") . EOL);
goaway(z_root());
return;
}
$aid = $r[0]['account_id'];
$email = $r[0]['account_email'];
$new_password = autoname(6) . mt_rand(100,9999);
$salt = random_string(32);
$password_encoded = hash('whirlpool', $salt . $new_password);
$r = q("UPDATE account SET account_salt = '%s', account_password = '%s', account_reset = '', account_flags = (account_flags & ~%d) where account_id = %d",
dbesc($salt),
dbesc($password_encoded),
intval(ACCOUNT_UNVERIFIED),
intval($aid)
);
if($r) {
$tpl = get_markup_template('pwdreset.tpl');
$o .= replace_macros($tpl,array(
'$lbl1' => t('Password Reset'),
'$lbl2' => t('Your password has been reset as requested.'),
'$lbl3' => t('Your new password is'),
'$lbl4' => t('Save or copy your new password - and then'),
'$lbl5' => '<a href="' . z_root() . '/login">' . t('click here to login') . '</a>.',
'$lbl6' => t('Your password may be changed from the <em>Settings</em> page after successful login.'),
'$newpass' => $new_password,
'$baseurl' => z_root()
));
info("Your password has been reset." . EOL);
$email_tpl = get_intltext_template("passchanged_eml.tpl");
$message = replace_macros($email_tpl, array(
'$sitename' => \App::$config['sitename'],
'$siteurl' => z_root(),
'$username' => sprintf( t('Site Member (%s)'), $email),
'$email' => $email,
'$new_password' => $new_password,
'$uid' => $newuid ));
$subject = email_header_encode( sprintf( t('Your password has changed at %s'), get_config('system','sitename')), 'UTF-8');
$res = mail($email,$subject,$message,
'From: ' . 'Administrator@' . $_SERVER['SERVER_NAME'] . "\n"
. 'Content-type: text/plain; charset=UTF-8' . "\n"
. 'Content-transfer-encoding: 8bit' );
return $o;
}
}
else {
$tpl = get_markup_template('lostpass.tpl');
$o .= replace_macros($tpl,array(
'$title' => t('Forgot your Password?'),
'$desc' => t('Enter your email address and submit to have your password reset. Then check your email for further instructions.'),
'$name' => t('Email Address'),
'$submit' => t('Reset')
));
return $o;
}
}
}

173
Zotlabs/Module/Magic.php Normal file
View File

@@ -0,0 +1,173 @@
<?php
namespace Zotlabs\Module;
@require_once('include/zot.php');
class Magic extends \Zotlabs\Web\Controller {
function init() {
$ret = array('success' => false, 'url' => '', 'message' => '');
logger('mod_magic: invoked', LOGGER_DEBUG);
logger('mod_magic: args: ' . print_r($_REQUEST,true),LOGGER_DATA);
$addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : '');
$dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : '');
$test = ((x($_REQUEST,'test')) ? intval($_REQUEST['test']) : 0);
$rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0);
$delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : '');
$parsed = parse_url($dest);
if(! $parsed) {
if($test) {
$ret['message'] .= 'could not parse ' . $dest . EOL;
return($ret);
}
goaway($dest);
}
$basepath = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '');
$x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1",
dbesc($basepath)
);
if(! $x) {
/*
* We have no records for, or prior communications with this hub.
* If an address was supplied, let's finger them to create a hub record.
* Otherwise we'll use the special address '[system]' which will return
* either a system channel or the first available normal channel. We don't
* really care about what channel is returned - we need the hub information
* from that response so that we can create signed auth packets destined
* for that hub.
*
*/
$ret = zot_finger((($addr) ? $addr : '[system]@' . $parsed['host']),null);
if($ret['success']) {
$j = json_decode($ret['body'],true);
if($j)
import_xchan($j);
// Now try again
$x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1",
dbesc($basepath)
);
}
}
if(! $x) {
if($rev)
goaway($dest);
else {
logger('mod_magic: no channels found for requested hub.' . print_r($_REQUEST,true));
if($test) {
$ret['message'] .= 'This site has no previous connections with ' . $basepath . EOL;
return $ret;
}
notice( t('Hub not found.') . EOL);
return;
}
}
// This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating.
// By default, we'll proceed without asking.
$arr = array(
'channel_id' => local_channel(),
'xchan' => $x[0],
'destination' => $dest,
'proceed' => true
);
call_hooks('magic_auth',$arr);
$dest = $arr['destination'];
if(! $arr['proceed']) {
if($test) {
$ret['message'] .= 'cancelled by plugin.' . EOL;
return $ret;
}
goaway($dest);
}
if((get_observer_hash()) && ($x[0]['hubloc_url'] === z_root())) {
// We are already authenticated on this site and a registered observer.
// Just redirect.
if($test) {
$ret['success'] = true;
$ret['message'] .= 'Local site - you are already authenticated.' . EOL;
return $ret;
}
$delegation_success = false;
if($delegate) {
$r = q("select * from channel left join hubloc on channel_hash = hubloc_hash where hubloc_addr = '%s' limit 1",
dbesc($delegate)
);
if($r && intval($r[0]['channel_id'])) {
$allowed = perm_is_allowed($r[0]['channel_id'],get_observer_hash(),'delegate');
if($allowed) {
$_SESSION['delegate_channel'] = $r[0]['channel_id'];
$_SESSION['delegate'] = get_observer_hash();
$_SESSION['account_id'] = intval($r[0]['channel_account_id']);
change_channel($r[0]['channel_id']);
$delegation_success = true;
}
}
}
// FIXME: check and honour local delegation
goaway($dest);
}
if(local_channel()) {
$channel = \App::get_channel();
$token = random_string();
$token_sig = base64url_encode(rsa_sign($token,$channel['channel_prvkey']));
$channel['token'] = $token;
$channel['token_sig'] = $token_sig;
\Zotlabs\Zot\Verify::create('auth',$channel['channel_id'],$token,$x[0]['hubloc_url']);
$target_url = $x[0]['hubloc_callback'] . '/?f=&auth=' . urlencode($channel['channel_address'] . '@' . \App::get_hostname())
. '&sec=' . $token . '&dest=' . urlencode($dest) . '&version=' . ZOT_REVISION;
if($delegate)
$target_url .= '&delegate=' . urlencode($delegate);
logger('mod_magic: redirecting to: ' . $target_url, LOGGER_DEBUG);
if($test) {
$ret['success'] = true;
$ret['url'] = $target_url;
$ret['message'] = 'token ' . $token . ' created for channel ' . $channel['channel_id'] . ' for url ' . $x[0]['hubloc_url'] . EOL;
return $ret;
}
goaway($target_url);
}
if($test) {
$ret['message'] = 'Not authenticated or invalid arguments to mod_magic' . EOL;
return $ret;
}
goaway($dest);
}
}

397
Zotlabs/Module/Mail.php Normal file
View File

@@ -0,0 +1,397 @@
<?php
namespace Zotlabs\Module;
require_once('include/acl_selectors.php');
require_once('include/message.php');
require_once('include/zot.php');
require_once("include/bbcode.php");
require_once('include/Contact.php');
class Mail extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
$replyto = ((x($_REQUEST,'replyto')) ? notags(trim($_REQUEST['replyto'])) : '');
$subject = ((x($_REQUEST,'subject')) ? notags(trim($_REQUEST['subject'])) : '');
$body = ((x($_REQUEST,'body')) ? escape_tags(trim($_REQUEST['body'])) : '');
$recipient = ((x($_REQUEST,'messageto')) ? notags(trim($_REQUEST['messageto'])) : '');
$rstr = ((x($_REQUEST,'messagerecip')) ? notags(trim($_REQUEST['messagerecip'])) : '');
$preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0);
$expires = ((x($_REQUEST,'expires')) ? datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expires']) : NULL_DATE);
// If we have a raw string for a recipient which hasn't been auto-filled,
// it means they probably aren't in our address book, hence we don't know
// if we have permission to send them private messages.
// finger them and find out before we try and send it.
if(! $recipient) {
$channel = \App::get_channel();
$ret = zot_finger($rstr,$channel);
if(! $ret['success']) {
notice( t('Unable to lookup recipient.') . EOL);
return;
}
$j = json_decode($ret['body'],true);
logger('message_post: lookup: ' . $url . ' ' . print_r($j,true));
if(! ($j['success'] && $j['guid'])) {
notice( t('Unable to communicate with requested channel.'));
return;
}
$x = import_xchan($j);
if(! $x['success']) {
notice( t('Cannot verify requested channel.'));
return;
}
$recipient = $x['hash'];
$their_perms = 0;
$global_perms = get_perms();
if($j['permissions']['data']) {
$permissions = crypto_unencapsulate($j['permissions'],$channel['channel_prvkey']);
if($permissions)
$permissions = json_decode($permissions);
logger('decrypted permissions: ' . print_r($permissions,true), LOGGER_DATA);
}
else
$permissions = $j['permissions'];
foreach($permissions as $k => $v) {
if($v) {
$their_perms = $their_perms | intval($global_perms[$k][1]);
}
}
if(! ($their_perms & PERMS_W_MAIL)) {
notice( t('Selected channel has private message restrictions. Send failed.'));
// reported issue: let's still save the message and continue. We'll just tell them
// that nothing useful is likely to happen. They might have spent hours on it.
// return;
}
}
// if(feature_enabled(local_channel(),'richtext')) {
// $body = fix_mce_lf($body);
// }
require_once('include/text.php');
linkify_tags($a, $body, local_channel());
if($preview) {
}
if(! $recipient) {
notice('No recipient found.');
\App::$argc = 2;
\App::$argv[1] = 'new';
return;
}
// We have a local_channel, let send_message use the session channel and save a lookup
$ret = send_message(0, $recipient, $body, $subject, $replyto, $expires);
if($ret['success']) {
xchan_mail_query($ret['mail']);
build_sync_packet(0,array('conv' => array($ret['conv']),'mail' => array(encode_mail($ret['mail'],true))));
}
else {
notice($ret['message']);
}
goaway(z_root() . '/mail/combined');
}
function get() {
$o = '';
nav_set_selected('messages');
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
}
$channel = \App::get_channel();
head_set_icon($channel['xchan_photo_s']);
$cipher = get_pconfig(local_channel(),'system','default_cipher');
if(! $cipher)
$cipher = 'aes256';
$tpl = get_markup_template('mail_head.tpl');
$header = replace_macros($tpl, array(
'$header' => t('Messages'),
));
if((argc() == 4) && (argv(2) === 'drop')) {
if(! intval(argv(3)))
return;
$cmd = argv(2);
$mailbox = argv(1);
$r = private_messages_drop(local_channel(), argv(3));
if($r) {
//info( t('Message deleted.') . EOL );
}
goaway(z_root() . '/mail/' . $mailbox);
}
if((argc() == 4) && (argv(2) === 'recall')) {
if(! intval(argv(3)))
return;
$cmd = argv(2);
$mailbox = argv(1);
$r = q("update mail set mail_recalled = 1 where id = %d and channel_id = %d",
intval(argv(3)),
intval(local_channel())
);
$x = q("select * from mail where id = %d and channel_id = %d",
intval(argv(3)),
intval(local_channel())
);
if($x) {
build_sync_packet(local_channel(),array('mail' => encode_mail($x[0],true)));
}
proc_run('php','include/notifier.php','mail',intval(argv(3)));
if($r) {
info( t('Message recalled.') . EOL );
}
goaway(z_root() . '/mail/' . $mailbox . '/' . argv(3));
}
if((argc() == 4) && (argv(2) === 'dropconv')) {
if(! intval(argv(3)))
return;
$cmd = argv(2);
$mailbox = argv(1);
$r = private_messages_drop(local_channel(), argv(3), true);
if($r)
info( t('Conversation removed.') . EOL );
goaway(z_root() . '/mail/' . $mailbox);
}
if((argc() > 1) && (argv(1) === 'new')) {
$plaintext = true;
$tpl = get_markup_template('msg-header.tpl');
$header = replace_macros($tpl, array(
'$baseurl' => z_root(),
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
'$nickname' => $channel['channel_address'],
'$linkurl' => t('Please enter a link URL:'),
'$expireswhen' => t('Expires YYYY-MM-DD HH:MM')
));
\App::$page['htmlhead'] .= $header;
$prename = '';
$preid = '';
if(x($_REQUEST,'hash')) {
$r = q("select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash
where abook_channel = %d and abook_xchan = '%s' limit 1",
intval(local_channel()),
dbesc($_REQUEST['hash'])
);
if(!$r) {
$r = q("select * from xchan where xchan_hash = '%s' and xchan_network = 'zot' limit 1",
dbesc($_REQUEST['hash'])
);
}
if($r) {
$prename = (($r[0]['abook_id']) ? $r[0]['xchan_name'] : $r[0]['xchan_addr']);
$preurl = $r[0]['xchan_url'];
$preid = (($r[0]['abook_id']) ? ($r[0]['xchan_hash']) : '');
}
else {
notice( t('Requested channel is not in this network') . EOL );
}
}
$tpl = get_markup_template('prv_message.tpl');
$o .= replace_macros($tpl,array(
'$new' => true,
'$header' => t('Send Private Message'),
'$to' => t('To:'),
'$prefill' => $prename,
'$preid' => $preid,
'$subject' => t('Subject:'),
'$subjtxt' => ((x($_REQUEST,'subject')) ? strip_tags($_REQUEST['subject']) : ''),
'$text' => ((x($_REQUEST,'body')) ? htmlspecialchars($_REQUEST['body'], ENT_COMPAT, 'UTF-8') : ''),
'$yourmessage' => t('Your message:'),
'$parent' => '',
'$attach' => t('Attach file'),
'$insert' => t('Insert web link'),
'$submit' => t('Send'),
'$defexpire' => '',
'$feature_expire' => ((feature_enabled(local_channel(),'content_expire')) ? true : false),
'$expires' => t('Set expiration date'),
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
'$encrypt' => t('Encrypt text'),
'$cipher' => $cipher,
));
return $o;
}
switch(argv(1)) {
case 'combined':
$mailbox = 'combined';
break;
case 'inbox':
$mailbox = 'inbox';
break;
case 'outbox':
$mailbox = 'outbox';
break;
default:
$mailbox = 'combined';
break;
}
$last_message = private_messages_list(local_channel(), $mailbox, 0, 1);
$mid = ((argc() > 2) && (intval(argv(2)))) ? argv(2) : $last_message[0]['id'];
$plaintext = true;
// if( local_channel() && feature_enabled(local_channel(),'richtext') )
// $plaintext = false;
if($mailbox == 'combined') {
$messages = private_messages_fetch_conversation(local_channel(), $mid, true);
}
else {
$messages = private_messages_fetch_message(local_channel(), $mid, true);
}
if(! $messages) {
//info( t('Message not found.') . EOL);
return;
}
if($messages[0]['to_xchan'] === $channel['channel_hash'])
\App::$poi = $messages[0]['from'];
else
\App::$poi = $messages[0]['to'];
// require_once('include/Contact.php');
// \App::set_widget('mail_conversant',vcard_from_xchan(\App::$poi,$get_observer_hash,'mail'));
$tpl = get_markup_template('msg-header.tpl');
\App::$page['htmlhead'] .= replace_macros($tpl, array(
'$nickname' => $channel['channel_address'],
'$baseurl' => z_root(),
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
'$linkurl' => t('Please enter a link URL:'),
'$expireswhen' => t('Expires YYYY-MM-DD HH:MM')
));
$mails = array();
$seen = 0;
$unknown = false;
foreach($messages as $message) {
$s = theme_attachments($message);
$mails[] = array(
'mailbox' => $mailbox,
'id' => $message['id'],
'mid' => $message['mid'],
'from_name' => $message['from']['xchan_name'],
'from_url' => chanlink_hash($message['from_xchan']),
'from_photo' => $message['from']['xchan_photo_s'],
'to_name' => $message['to']['xchan_name'],
'to_url' => chanlink_hash($message['to_xchan']),
'to_photo' => $message['to']['xchan_photo_s'],
'subject' => $message['title'],
'body' => smilies(bbcode($message['body'])),
'attachments' => $s,
'delete' => t('Delete message'),
'dreport' => t('Delivery report'),
'recall' => t('Recall message'),
'can_recall' => (($channel['channel_hash'] == $message['from_xchan']) ? true : false),
'is_recalled' => (intval($message['mail_recalled']) ? t('Message has been recalled.') : ''),
'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c'),
);
$seen = $message['seen'];
}
$recp = (($message['from_xchan'] === $channel['channel_hash']) ? 'to' : 'from');
$tpl = get_markup_template('mail_display.tpl');
$o = replace_macros($tpl, array(
'$mailbox' => $mailbox,
'$prvmsg_header' => $message['title'],
'$thread_id' => $mid,
'$thread_subject' => $message['title'],
'$thread_seen' => $seen,
'$delete' => t('Delete Conversation'),
'$canreply' => (($unknown) ? false : '1'),
'$unknown_text' => t("No secure communications available. You <strong>may</strong> be able to respond from the sender's profile page."),
'$mails' => $mails,
// reply
'$header' => t('Send Reply'),
'$to' => t('To:'),
'$reply' => true,
'$subject' => t('Subject:'),
'$subjtxt' => $message['title'],
'$yourmessage' => sprintf(t('Your message for %s (%s):'), $message[$recp]['xchan_name'], $message[$recp]['xchan_addr']),
'$text' => '',
'$parent' => $message['parent_mid'],
'$recphash' => $message[$recp]['xchan_hash'],
'$attach' => t('Attach file'),
'$insert' => t('Insert web link'),
'$submit' => t('Submit'),
'$defexpire' => '',
'$feature_expire' => ((feature_enabled(local_channel(),'content_expire')) ? true : false),
'$expires' => t('Set expiration date'),
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
'$encrypt' => t('Encrypt text'),
'$cipher' => $cipher,
));
return $o;
}
}

183
Zotlabs/Module/Manage.php Normal file
View File

@@ -0,0 +1,183 @@
<?php
namespace Zotlabs\Module;
class Manage extends \Zotlabs\Web\Controller {
function get() {
if((! get_account_id()) || ($_SESSION['delegate'])) {
notice( t('Permission denied.') . EOL);
return;
}
require_once('include/security.php');
$change_channel = ((argc() > 1) ? intval(argv(1)) : 0);
if((argc() > 2) && (argv(2) === 'default')) {
$r = q("select channel_id from channel where channel_id = %d and channel_account_id = %d limit 1",
intval($change_channel),
intval(get_account_id())
);
if($r) {
q("update account set account_default_channel = %d where account_id = %d",
intval($change_channel),
intval(get_account_id())
);
}
goaway(z_root() . '/manage');
}
if($change_channel) {
$r = change_channel($change_channel);
if((argc() > 2) && !(argv(2) === 'default')) {
goaway(z_root() . '/' . implode('/',array_slice(\App::$argv,2))); // Go to whatever is after /manage/, but with the new channel
}
else {
if($r && $r['channel_startpage'])
goaway(z_root() . '/' . $r['channel_startpage']); // If nothing extra is specified, go to the default page
}
goaway(z_root());
}
$channels = null;
if(local_channel()) {
$r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and channel_removed = 0 order by channel_name ",
intval(get_account_id())
);
$account = \App::get_account();
if($r && count($r)) {
$channels = $r;
for($x = 0; $x < count($channels); $x ++) {
$channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']);
$channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : '');
$channels[$x]['default_links'] = '1';
$c = q("SELECT id, item_wall FROM item
WHERE item_unseen = 1 and uid = %d " . item_normal(),
intval($channels[$x]['channel_id'])
);
if($c) {
foreach ($c as $it) {
if(intval($it['item_wall']))
$channels[$x]['home'] ++;
else
$channels[$x]['network'] ++;
}
}
$intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
intval($channels[$x]['channel_id'])
);
if($intr)
$channels[$x]['intros'] = intval($intr[0]['total']);
$mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
intval($channels[$x]['channel_id']),
dbesc($channels[$x]['channel_hash'])
);
if($mails)
$channels[$x]['mail'] = intval($mails[0]['total']);
$events = q("SELECT type, start, adjust FROM `event`
WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0
ORDER BY `start` ASC ",
intval($channels[$x]['channel_id']),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
);
if($events) {
$channels[$x]['all_events'] = count($events);
if($channels[$x]['all_events']) {
$str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d');
foreach($events as $e) {
$bd = false;
if($e['type'] === 'birthday') {
$channels[$x]['birthdays'] ++;
$bd = true;
}
else {
$channels[$x]['events'] ++;
}
if(datetime_convert('UTC', ((intval($e['adjust'])) ? date_default_timezone_get() : 'UTC'), $e['start'], 'Y-m-d') === $str_now) {
$channels[$x]['all_events_today'] ++;
if($bd)
$channels[$x]['birthdays_today'] ++;
else
$channels[$x]['events_today'] ++;
}
}
}
}
}
}
$r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0",
intval(get_account_id())
);
$limit = account_service_class_fetch(get_account_id(),'total_identities');
if($limit !== false) {
$channel_usage_message = sprintf( t("You have created %1$.0f of %2$.0f allowed channels."), $r[0]['total'], $limit);
}
else {
$channel_usage_message = '';
}
}
$create = array( 'new_channel', t('Create a new channel'), t('Create New'));
$delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where
abook_channel = %d and (abook_their_perms & %d) > 0",
intval(local_channel()),
intval(PERMS_A_DELEGATE)
);
if($delegates) {
for($x = 0; $x < count($delegates); $x ++) {
$delegates[$x]['link'] = 'magic?f=&dest=' . urlencode($delegates[$x]['xchan_url'])
. '&delegate=' . urlencode($delegates[$x]['xchan_addr']);
$delegates[$x]['channel_name'] = $delegates[$x]['xchan_name'];
$delegates[$x]['delegate'] = 1;
}
}
else {
$delegates = null;
}
$o = replace_macros(get_markup_template('channels.tpl'), array(
'$header' => t('Channel Manager'),
'$msg_selected' => t('Current Channel'),
'$selected' => local_channel(),
'$desc' => t('Switch to one of your channels by selecting it.'),
'$msg_default' => t('Default Channel'),
'$msg_make_default' => t('Make Default'),
'$create' => $create,
'$all_channels' => $channels,
'$mail_format' => t('%d new messages'),
'$intros_format' => t('%d new introductions'),
'$channel_usage_message' => $channel_usage_message,
'$delegated_desc' => t('Delegated Channel'),
'$delegates' => $delegates
));
return $o;
}
}

84
Zotlabs/Module/Match.php Normal file
View File

@@ -0,0 +1,84 @@
<?php
namespace Zotlabs\Module;
/**
* @brief Controller for /match.
*
* It takes keywords from your profile and queries the directory server for
* matching keywords from other profiles.
*
* @FIXME this has never been properly ported from Friendica.
*
* @param App &$a
* @return void|string
*/
class Match extends \Zotlabs\Web\Controller {
function get() {
$o = '';
if (! local_channel())
return;
$_SESSION['return_url'] = z_root() . '/' . \App::$cmd;
$o .= '<h2>' . t('Profile Match') . '</h2>';
$r = q("SELECT `keywords` FROM `profile` WHERE `is_default` = 1 AND `uid` = %d LIMIT 1",
intval(local_channel())
);
if (! count($r))
return;
if (! $r[0]['keywords']) {
notice( t('No keywords to match. Please add keywords to your default profile.') . EOL);
return;
}
$params = array();
$tags = trim($r[0]['keywords']);
if ($tags) {
$params['s'] = $tags;
if (\App::$pager['page'] != 1)
$params['p'] = \App::$pager['page'];
// if(strlen(get_config('system','directory_submit_url')))
// $x = post_url('http://dir.friendica.com/msearch', $params);
// else
// $x = post_url(z_root() . '/msearch', $params);
$j = json_decode($x);
if ($j->total) {
\App::set_pager_total($j->total);
\App::set_pager_itemspage($j->items_page);
}
if (count($j->results)) {
$tpl = get_markup_template('match.tpl');
foreach ($j->results as $jj) {
$connlnk = z_root() . '/follow/?url=' . $jj->url;
$o .= replace_macros($tpl,array(
'$url' => zid($jj->url),
'$name' => $jj->name,
'$photo' => $jj->photo,
'$inttxt' => ' ' . t('is interested in:'),
'$conntxt' => t('Connect'),
'$connlnk' => $connlnk,
'$tags' => $jj->tags
));
}
} else {
info( t('No matches') . EOL);
}
}
$o .= cleardiv();
$o .= paginate($a);
return $o;
}
}

173
Zotlabs/Module/Menu.php Normal file
View File

@@ -0,0 +1,173 @@
<?php
namespace Zotlabs\Module;
require_once('include/menu.php');
require_once('include/identity.php');
class Menu extends \Zotlabs\Web\Controller {
function init() {
if (array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) {
$sys = get_sys_channel();
if ($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
}
function post() {
$uid = local_channel();
if(array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) {
$sys = get_sys_channel();
$uid = intval($sys['channel_id']);
\App::$is_sys = true;
}
if(! $uid)
return;
$_REQUEST['menu_channel_id'] = $uid;
if($_REQUEST['menu_bookmark'])
$_REQUEST['menu_flags'] |= MENU_BOOKMARK;
if($_REQUEST['menu_system'])
$_REQUEST['menu_flags'] |= MENU_SYSTEM;
$menu_id = ((argc() > 1) ? intval(argv(1)) : 0);
if($menu_id) {
$_REQUEST['menu_id'] = intval(argv(1));
$r = menu_edit($_REQUEST);
if($r) {
menu_sync_packet($uid,get_observer_hash(),$menu_id);
//info( t('Menu updated.') . EOL);
goaway(z_root() . '/mitem/' . $menu_id . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
else
notice( t('Unable to update menu.'). EOL);
}
else {
$r = menu_create($_REQUEST);
if($r) {
menu_sync_packet($uid,get_observer_hash(),$r);
//info( t('Menu created.') . EOL);
goaway(z_root() . '/mitem/' . $r . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
else
notice( t('Unable to create menu.'). EOL);
}
}
function get() {
$uid = local_channel();
if (\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
$uid = intval($sys['channel_id']);
}
if(! $uid) {
notice( t('Permission denied.') . EOL);
return '';
}
if(argc() == 1) {
// list menus
$x = menu_list($uid);
if($x) {
for($y = 0; $y < count($x); $y ++) {
$m = menu_fetch($x[$y]['menu_name'],$uid,get_observer_hash());
if($m)
$x[$y]['element'] = '[element]' . base64url_encode(json_encode(menu_element($m))) . '[/element]';
$x[$y]['bookmark'] = (($x[$y]['menu_flags'] & MENU_BOOKMARK) ? true : false);
}
}
$create = replace_macros(get_markup_template('menuedit.tpl'), array(
'$menu_name' => array('menu_name', t('Menu Name'), '', t('Unique name (not visible on webpage) - required'), '*'),
'$menu_desc' => array('menu_desc', t('Menu Title'), '', t('Visible on webpage - leave empty for no title'), ''),
'$menu_bookmark' => array('menu_bookmark', t('Allow Bookmarks'), 0 , t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))),
'$submit' => t('Submit and proceed'),
'$sys' => \App::$is_sys,
'$display' => 'none'
));
$o = replace_macros(get_markup_template('menulist.tpl'),array(
'$title' => t('Menus'),
'$create' => $create,
'$menus' => $x,
'$nametitle' => t('Menu Name'),
'$desctitle' => t('Menu Title'),
'$edit' => t('Edit'),
'$drop' => t('Drop'),
'$created' => t('Created'),
'$edited' => t('Edited'),
'$new' => t('New'),
'$bmark' => t('Bookmarks allowed'),
'$hintnew' => t('Create'),
'$hintdrop' => t('Delete this menu'),
'$hintcontent' => t('Edit menu contents'),
'$hintedit' => t('Edit this menu'),
'$sys' => \App::$is_sys
));
return $o;
}
if(argc() > 1) {
if(intval(argv(1))) {
if(argc() == 3 && argv(2) == 'drop') {
menu_sync_packet($uid,get_observer_hash(),intval(argv(1)),true);
$r = menu_delete_id(intval(argv(1)),$uid);
if(!$r)
notice( t('Menu could not be deleted.'). EOL);
goaway(z_root() . '/menu' . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
$m = menu_fetch_id(intval(argv(1)),$uid);
if(! $m) {
notice( t('Menu not found.') . EOL);
return '';
}
$o = replace_macros(get_markup_template('menuedit.tpl'), array(
'$header' => t('Edit Menu'),
'$sys' => \App::$is_sys,
'$menu_id' => intval(argv(1)),
'$menu_edit_link' => 'mitem/' . intval(argv(1)) . ((\App::$is_sys) ? '?f=&sys=1' : ''),
'$hintedit' => t('Add or remove entries to this menu'),
'$editcontents' => t('Edit menu contents'),
'$menu_name' => array('menu_name', t('Menu name'), $m['menu_name'], t('Must be unique, only seen by you'), '*'),
'$menu_desc' => array('menu_desc', t('Menu title'), $m['menu_desc'], t('Menu title as seen by others'), ''),
'$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), (($m['menu_flags'] & MENU_BOOKMARK) ? 1 : 0), t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))),
'$menu_system' => (($m['menu_flags'] & MENU_SYSTEM) ? 1 : 0),
'$submit' => t('Submit and proceed')
));
return $o;
}
else {
notice( t('Not found.') . EOL);
return;
}
}
}
}

110
Zotlabs/Module/Message.php Normal file
View File

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

245
Zotlabs/Module/Mitem.php Normal file
View File

@@ -0,0 +1,245 @@
<?php
namespace Zotlabs\Module;
require_once('include/menu.php');
require_once('include/acl_selectors.php');
class Mitem extends \Zotlabs\Web\Controller {
function init() {
$uid = local_channel();
if(array_key_exists('sys',$_REQUEST) && $_REQUEST['sys'] && is_site_admin()) {
$sys = get_sys_channel();
$uid = intval($sys['channel_id']);
\App::$is_sys = true;
}
if(! $uid)
return;
if(argc() < 2)
return;
$m = menu_fetch_id(intval(argv(1)),$uid);
if(! $m) {
notice( t('Menu not found.') . EOL);
return '';
}
\App::$data['menu'] = $m;
}
function post() {
$uid = local_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
$uid = intval($sys['channel_id']);
}
if(! $uid) {
return;
}
if(! \App::$data['menu'])
return;
if(!$_REQUEST['mitem_desc'] || !$_REQUEST['mitem_link']) {
notice( t('Unable to create element.') . EOL);
return;
}
$_REQUEST['mitem_channel_id'] = $uid;
$_REQUEST['menu_id'] = \App::$data['menu']['menu_id'];
$_REQUEST['mitem_flags'] = 0;
if($_REQUEST['usezid'])
$_REQUEST['mitem_flags'] |= MENU_ITEM_ZID;
if($_REQUEST['newwin'])
$_REQUEST['mitem_flags'] |= MENU_ITEM_NEWWIN;
$mitem_id = ((argc() > 2) ? intval(argv(2)) : 0);
if($mitem_id) {
$_REQUEST['mitem_id'] = $mitem_id;
$r = menu_edit_item($_REQUEST['menu_id'],$uid,$_REQUEST);
if($r) {
menu_sync_packet($uid,get_observer_hash(),$_REQUEST['menu_id']);
//info( t('Menu element updated.') . EOL);
goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
else
notice( t('Unable to update menu element.') . EOL);
}
else {
$r = menu_add_item($_REQUEST['menu_id'],$uid,$_REQUEST);
if($r) {
menu_sync_packet($uid,get_observer_hash(),$_REQUEST['menu_id']);
//info( t('Menu element added.') . EOL);
if($_REQUEST['submit']) {
goaway(z_root() . '/menu' . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
if($_REQUEST['submit-more']) {
goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . '?f=&display=block' . ((\App::$is_sys) ? '&sys=1' : '') );
}
}
else
notice( t('Unable to add menu element.') . EOL);
}
}
function get() {
$uid = local_channel();
$channel = \App::get_channel();
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
$uid = intval($sys['channel_id']);
$channel = $sys;
$ob_hash = $sys['xchan_hash'];
}
if(! $uid) {
notice( t('Permission denied.') . EOL);
return '';
}
if(argc() < 2 || (! \App::$data['menu'])) {
notice( t('Not found.') . EOL);
return '';
}
$m = menu_fetch(\App::$data['menu']['menu_name'],$uid,$ob_hash);
\App::$data['menu_item'] = $m;
$menu_list = menu_list($uid);
foreach($menu_list as $menus) {
if($menus['menu_name'] != $m['menu']['menu_name'])
$menu_names[] = $menus['menu_name'];
}
$acl = new \Zotlabs\Access\AccessList($channel);
$lockstate = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock');
if(argc() == 2) {
$r = q("select * from menu_item where mitem_menu_id = %d and mitem_channel_id = %d order by mitem_order asc, mitem_desc asc",
intval(\App::$data['menu']['menu_id']),
intval($uid)
);
if($_GET['display']) {
$display = $_GET['display'];
}
else {
$display = (($r) ? 'none' : 'block');
}
$create = replace_macros(get_markup_template('mitemedit.tpl'), array(
'$menu_id' => \App::$data['menu']['menu_id'],
'$permissions' => t('Menu Item Permissions'),
'$permdesc' => t("\x28click to open/close\x29"),
'$aclselect' => populate_acl($acl->get(),false),
'$mitem_desc' => array('mitem_desc', t('Link Name'), '', 'Visible name of the link','*'),
'$mitem_link' => array('mitem_link', t('Link or Submenu Target'), '', t('Enter URL of the link or select a menu name to create a submenu'), '*', 'list="menu-names"'),
'$usezid' => array('usezid', t('Use magic-auth if available'), true, '', array(t('No'), t('Yes'))),
'$newwin' => array('newwin', t('Open link in new window'), false,'', array(t('No'), t('Yes'))),
'$mitem_order' => array('mitem_order', t('Order in list'),'0',t('Higher numbers will sink to bottom of listing')),
'$submit' => t('Submit and finish'),
'$submit_more' => t('Submit and continue'),
'$display' => $display,
'$lockstate' => $lockstate,
'$menu_names' => $menu_names,
'$sys' => \App::$is_sys
));
$o .= replace_macros(get_markup_template('mitemlist.tpl'),array(
'$title' => t('Menu:'),
'$create' => $create,
'$nametitle' => t('Link Name'),
'$targettitle' => t('Link Target'),
'$menuname' => \App::$data['menu']['menu_name'],
'$menudesc' => \App::$data['menu']['menu_desc'],
'$edmenu' => t('Edit menu'),
'$menu_id' => \App::$data['menu']['menu_id'],
'$mlist' => $r,
'$edit' => t('Edit element'),
'$drop' => t('Drop element'),
'$new' => t('New element'),
'$hintmenu' => t('Edit this menu container'),
'$hintnew' => t('Add menu element'),
'$hintdrop' => t('Delete this menu item'),
'$hintedit' => t('Edit this menu item'),
));
return $o;
}
if(argc() > 2) {
if(intval(argv(2))) {
$m = q("select * from menu_item where mitem_id = %d and mitem_channel_id = %d limit 1",
intval(argv(2)),
intval($uid)
);
if(! $m) {
notice( t('Menu item not found.') . EOL);
goaway(z_root() . '/menu'. ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
$mitem = $m[0];
$lockstate = (($mitem['allow_cid'] || $mitem['allow_gid'] || $mitem['deny_cid'] || $mitem['deny_gid']) ? 'lock' : 'unlock');
if(argc() == 4 && argv(3) == 'drop') {
menu_sync_packet($uid,get_observer_hash(),$mitem['mitem_menu_id']);
$r = menu_del_item($mitem['mitem_menu_id'], $uid, intval(argv(2)));
menu_sync_packet($uid,get_observer_hash(),$mitem['mitem_menu_id']);
if($r)
info( t('Menu item deleted.') . EOL);
else
notice( t('Menu item could not be deleted.'). EOL);
goaway(z_root() . '/mitem/' . $mitem['mitem_menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
// edit menu item
$o = replace_macros(get_markup_template('mitemedit.tpl'), array(
'$header' => t('Edit Menu Element'),
'$menu_id' => \App::$data['menu']['menu_id'],
'$permissions' => t('Menu Item Permissions'),
'$permdesc' => t("\x28click to open/close\x29"),
'$aclselect' => populate_acl($mitem,false),
'$mitem_id' => intval(argv(2)),
'$mitem_desc' => array('mitem_desc', t('Link text'), $mitem['mitem_desc'], '','*'),
'$mitem_link' => array('mitem_link', t('Link or Submenu Target'), $mitem['mitem_link'], 'Enter URL of the link or select a menu name to create a submenu', '*', 'list="menu-names"'),
'$usezid' => array('usezid', t('Use magic-auth if available'), (($mitem['mitem_flags'] & MENU_ITEM_ZID) ? 1 : 0), '', array(t('No'), t('Yes'))),
'$newwin' => array('newwin', t('Open link in new window'), (($mitem['mitem_flags'] & MENU_ITEM_NEWWIN) ? 1 : 0),'', array(t('No'), t('Yes'))),
'$mitem_order' => array('mitem_order', t('Order in list'),$mitem['mitem_order'],t('Higher numbers will sink to bottom of listing')),
'$submit' => t('Submit'),
'$lockstate' => $lockstate,
'$menu_names' => $menu_names
));
return $o;
}
}
}
}

146
Zotlabs/Module/Mood.php Normal file
View File

@@ -0,0 +1,146 @@
<?php
namespace Zotlabs\Module;
require_once('include/security.php');
require_once('include/bbcode.php');
require_once('include/items.php');
class Mood extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
$uid = local_channel();
$channel = \App::get_channel();
$verb = notags(trim($_GET['verb']));
if(! $verb)
return;
$verbs = get_mood_verbs();
if(! array_key_exists($verb,$verbs))
return;
$activity = ACTIVITY_MOOD . '#' . urlencode($verb);
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : 0);
logger('mood: verb ' . $verb, LOGGER_DEBUG);
if($parent) {
$r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid
from item where id = %d and parent = %d and uid = %d limit 1",
intval($parent),
intval($parent),
intval($uid)
);
if(count($r)) {
$parent_mid = $r[0]['mid'];
$private = $r[0]['item_private'];
$allow_cid = $r[0]['allow_cid'];
$allow_gid = $r[0]['allow_gid'];
$deny_cid = $r[0]['deny_cid'];
$deny_gid = $r[0]['deny_gid'];
}
}
else {
$private = 0;
$allow_cid = $channel['channel_allow_cid'];
$allow_gid = $channel['channel_allow_gid'];
$deny_cid = $channel['channel_deny_cid'];
$deny_gid = $channel['channel_deny_gid'];
}
$poster = \App::get_observer();
$mid = item_message_id();
$action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]);
$arr = array();
$arr['aid'] = get_account_id();
$arr['uid'] = $uid;
$arr['mid'] = $mid;
$arr['parent_mid'] = (($parent_mid) ? $parent_mid : $mid);
$arr['author_xchan'] = $poster['xchan_hash'];
$arr['owner_xchan'] = (($parent_mid) ? $r[0]['owner_xchan'] : $poster['xchan_hash']);
$arr['title'] = '';
$arr['allow_cid'] = $allow_cid;
$arr['allow_gid'] = $allow_gid;
$arr['deny_cid'] = $deny_cid;
$arr['deny_gid'] = $deny_gid;
$arr['item_private'] = $private;
$arr['verb'] = $activity;
$arr['body'] = $action;
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
$arr['item_unseen'] = 1;
if(! $parent_mid)
$item['item_thread_top'] = 1;
if ((! $arr['plink']) && intval($arr['item_thread_top'])) {
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
}
$post = item_store($arr);
$item_id = $post['item_id'];
if($item_id) {
proc_run('php',"include/notifier.php","activity", $item_id);
}
call_hooks('post_local_end', $arr);
if($_SESSION['return_url'])
goaway(z_root() . '/' . $_SESSION['return_url']);
return;
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : '0');
$verbs = get_mood_verbs();
$shortlist = array();
foreach($verbs as $k => $v)
if($v !== 'NOTRANSLATION')
$shortlist[] = array($k,$v);
$tpl = get_markup_template('mood_content.tpl');
$o = replace_macros($tpl,array(
'$title' => t('Mood'),
'$desc' => t('Set your current mood and tell your friends'),
'$verbs' => $shortlist,
'$parent' => $parent,
'$submit' => t('Submit'),
));
return $o;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Zotlabs\Module;
class Msearch extends \Zotlabs\Web\Controller {
function post() {
$perpage = (($_POST['n']) ? $_POST['n'] : 80);
$page = (($_POST['p']) ? intval($_POST['p'] - 1) : 0);
$startrec = (($page+1) * $perpage) - $perpage;
$search = $_POST['s'];
if(! strlen($search))
killme();
$r = q("SELECT COUNT(*) AS `total` FROM `profile` LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` WHERE `is_default` = 1 AND `user`.`hidewall` = 0 AND MATCH `keywords` AGAINST ('%s') ",
dbesc($search)
);
if(count($r))
$total = $r[0]['total'];
$r = q("SELECT `keywords`, `username`, `nickname`, `user`.`uid` FROM `user` LEFT JOIN `profile` ON `user`.`uid` = `profile`.`uid` WHERE `is_default` = 1 AND `user`.`hidewall` = 0 AND MATCH `keywords` AGAINST ('%s') LIMIT %d , %d ",
dbesc($search),
intval($startrec),
intval($perpage)
);
$results = array();
if(count($r)) {
foreach($r as $rr)
$results[] = array(
'name' => $rr['name'],
'url' => z_root() . '/channel/' . $rr['nickname'],
'photo' => z_root() . '/photo/avatar/' . $rr['uid'],
'tags' => str_replace(array(',',' '),array(' ',' '),$rr['keywords'])
);
}
$output = array('total' => $total, 'items_page' => $perpage, 'page' => $page + 1, 'results' => $results);
echo json_encode($output);
killme();
}
}

532
Zotlabs/Module/Network.php Normal file
View File

@@ -0,0 +1,532 @@
<?php
namespace Zotlabs\Module;
require_once('include/items.php');
require_once('include/group.php');
require_once('include/contact_widgets.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/PermissionDescription.php');
class Network extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if(count($_GET) < 2) {
$network_options = get_pconfig(local_channel(),'system','network_page_default');
if($network_options)
goaway('network' . '?f=&' . $network_options);
}
$channel = \App::get_channel();
\App::$profile_uid = local_channel();
head_set_icon($channel['xchan_photo_s']);
}
function get($update = 0, $load = false) {
if(! local_channel()) {
$_SESSION['return_url'] = \App::$query_string;
return login(false);
}
if($load)
$_SESSION['loadtime'] = datetime_convert();
$arr = array('query' => \App::$query_string);
call_hooks('network_content_init', $arr);
$channel = \App::get_channel();
$item_normal = item_normal();
$datequery = $datequery2 = '';
$group = 0;
$nouveau = false;
$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']) : '');
$nouveau = ((x($_GET,'new')) ? intval($_GET['new']) : 0);
$gid = ((x($_GET,'gid')) ? intval($_GET['gid']) : 0);
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
$verb = ((x($_REQUEST,'verb')) ? $_REQUEST['verb'] : '');
$search = (($_GET['search']) ? $_GET['search'] : '');
if($search) {
if(strpos($search,'@') === 0) {
$r = q("select abook_id from abook left join xchan on abook_xchan = xchan_hash where xchan_name = '%s' and abook_channel = %d limit 1",
dbesc(substr($search,1)),
intval(local_channel())
);
if($r) {
$_GET['cid'] = $r[0]['abook_id'];
$search = $_GET['search'] = '';
}
}
elseif(strpos($search,'#') === 0) {
$hashtags = substr($search,1);
$search = $_GET['search'] = '';
}
}
if($datequery)
$_GET['order'] = 'post';
// filter by collection (e.g. group)
if($gid) {
$r = q("SELECT * FROM groups WHERE id = %d AND uid = %d LIMIT 1",
intval($gid),
intval(local_channel())
);
if(! $r) {
if($update)
killme();
notice( t('No such group') . EOL );
goaway(z_root() . '/network');
// NOTREACHED
}
$group = $gid;
$group_hash = $r[0]['hash'];
$def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>');
}
$o = '';
// if no tabs are selected, defaults to comments
$cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0);
$star = ((x($_GET,'star')) ? intval($_GET['star']) : 0);
$order = ((x($_GET,'order')) ? notags($_GET['order']) : 'comment');
$liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0);
$conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0);
$spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0);
$cmin = ((x($_GET,'cmin')) ? intval($_GET['cmin']) : 0);
$cmax = ((x($_GET,'cmax')) ? intval($_GET['cmax']) : 99);
$firehose = ((x($_GET,'fh')) ? intval($_GET['fh']) : 0);
$file = ((x($_GET,'file')) ? $_GET['file'] : '');
$deftag = '';
if(x($_GET,'search') || x($_GET,'file'))
$nouveau = true;
if($cid) {
$r = q("SELECT abook_xchan FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
intval($cid),
intval(local_channel())
);
if(! $r) {
if($update) {
killme();
}
notice( t('No such channel') . EOL );
goaway(z_root() . '/network');
// NOTREACHED
}
if($_GET['pf'] === '1')
$deftag = '@' . t('forum') . '+' . intval($cid) . '+';
else
$def_acl = array('allow_cid' => '<' . $r[0]['abook_xchan'] . '>');
}
if(! $update) {
$tabs = network_tabs();
$o .= $tabs;
// search terms header
if($search) {
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT,'UTF-8')
));
}
nav_set_selected('network');
$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']
);
$private_editing = ((($group || $cid) && (! intval($_GET['pf']))) ? true : false);
$x = array(
'is_owner' => true,
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
'lockstate' => (($private_editing || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => populate_acl((($private_editing) ? $def_acl : $channel_acl), true, \PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'),
'bang' => (($private_editing) ? '!' : ''),
'visitor' => true,
'profile_uid' => local_channel(),
'editor_autocomplete' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
if($deftag)
$x['pretext'] = $deftag;
$status_editor = status_editor($a,$x);
$o .= $status_editor;
}
// We don't have to deal with ACL's on this page. You're looking at everything
// that belongs to you, hence you can see all of it. We will filter by group if
// desired.
$sql_options = (($star)
? " and item_starred = 1 "
: '');
$sql_nets = '';
$sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE item_thread_top = 1 $sql_options ) ";
if($group) {
$contact_str = '';
$contacts = group_get_members($group);
if($contacts) {
foreach($contacts as $c) {
if($contact_str)
$contact_str .= ',';
$contact_str .= "'" . $c['xchan'] . "'";
}
}
else {
$contact_str = ' 0 ';
info( t('Privacy group is empty'));
}
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent $item_normal ) ";
$x = group_rec_byhash(local_channel(), $group_hash);
if($x) {
$title = replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => t('Privacy group: ') . $x['name']
));
}
$o = $tabs;
$o .= $title;
$o .= $status_editor;
}
elseif($cid) {
$r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and abook_blocked = 0 limit 1",
intval($cid),
intval(local_channel())
);
if($r) {
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) $item_normal ) ";
$title = replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => '<a href="' . zid($r[0]['xchan_url']) . '" ><img src="' . zid($r[0]['xchan_photo_s']) . '" alt="' . urlencode($r[0]['xchan_name']) . '" /></a> <a href="' . zid($r[0]['xchan_url']) . '" >' . $r[0]['xchan_name'] . '</a>'
));
$o = $tabs;
$o .= $title;
$o .= $status_editor;
}
else {
notice( t('Invalid connection.') . EOL);
goaway(z_root() . '/network');
}
}
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(! $update) {
// The special div is needed for liveUpdate to kick in for this page.
// We only launch liveUpdate if you aren't filtering in some incompatible
// way and also you aren't writing a comment (discovered in javascript).
if($gid || $cid || $cmin || ($cmax != 99) || $star || $liked || $conv || $spam || $nouveau || $list)
$firehose = 0;
$maxheight = get_pconfig(local_channel(),'system','network_divmore_height');
if(! $maxheight)
$maxheight = 400;
$o .= '<div id="live-network"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . local_channel()
. "; 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' => 'network',
'$uid' => ((local_channel()) ? local_channel() : '0'),
'$gid' => (($gid) ? $gid : '0'),
'$cid' => (($cid) ? $cid : '0'),
'$cmin' => (($cmin) ? $cmin : '0'),
'$cmax' => (($cmax) ? $cmax : '0'),
'$star' => (($star) ? $star : '0'),
'$liked' => (($liked) ? $liked : '0'),
'$conv' => (($conv) ? $conv : '0'),
'$spam' => (($spam) ? $spam : '0'),
'$fh' => (($firehose) ? $firehose : '0'),
'$nouveau' => (($nouveau) ? $nouveau : '0'),
'$wall' => '0',
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => (($search) ? $search : ''),
'$order' => $order,
'$file' => $file,
'$cats' => $category,
'$tags' => $hashtags,
'$dend' => $datequery,
'$mid' => '',
'$verb' => $verb,
'$dbegin' => $datequery2
));
}
$sql_extra3 = '';
if($datequery) {
$sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
}
if($datequery2) {
$sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
$sql_extra2 = (($nouveau) ? '' : " AND item.parent = item.id ");
$sql_extra3 = (($nouveau) ? '' : $sql_extra3);
if(x($_GET,'search')) {
$search = escape_tags($_GET['search']);
if(strpos($search,'#') === 0) {
$sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG);
}
else {
$sql_extra .= sprintf(" AND item.body like '%s' ",
dbesc(protect_sprintf('%' . $search . '%'))
);
}
}
if($verb) {
$sql_extra .= sprintf(" AND item.verb like '%s' ",
dbesc(protect_sprintf('%' . $verb . '%'))
);
}
if(strlen($file)) {
$sql_extra .= term_query('item',$file,TERM_FILE);
}
if($conv) {
$sql_extra .= sprintf(" AND parent IN (SELECT distinct(parent) from item where ( author_xchan like '%s' or item_mentionsme = 1 )) ",
dbesc(protect_sprintf($channel['channel_hash']))
);
}
if($update && ! $load) {
// only setup pagination on initial page view
$pager_sql = '';
}
else {
$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(($cmin != 0) || ($cmax != 99)) {
// Not everybody who shows up in the network stream will be in your address book.
// By default those that aren't are assumed to have closeness = 99; but this isn't
// recorded anywhere. So if cmax is 99, we'll open the search up to anybody in
// the stream with a NULL address book entry.
$sql_nets .= " AND ";
if($cmax == 99)
$sql_nets .= " ( ";
$sql_nets .= "( abook.abook_closeness >= " . intval($cmin) . " ";
$sql_nets .= " AND abook.abook_closeness <= " . intval($cmax) . " ) ";
if($cmax == 99)
$sql_nets .= " OR abook.abook_closeness IS NULL ) ";
}
$abook_uids = " and abook.abook_channel = " . local_channel() . " ";
if($firehose && (! get_config('system','disable_discover_tab'))) {
require_once('include/identity.php');
$sys = get_sys_channel();
$uids = " and item.uid = " . intval($sys['channel_id']) . " ";
\App::$data['firehose'] = intval($sys['channel_id']);
}
else {
$uids = " and item.uid = " . local_channel() . " ";
}
if(get_pconfig(local_channel(),'system','network_list_mode'))
$page_mode = 'list';
else
$page_mode = 'client';
$simple_update = (($update) ? " and item_unseen = 1 " : '');
// This fixes a very subtle bug so I'd better explain it. You wake up in the morning or return after a day
// or three and look at your matrix page - after opening up your browser. The first page loads just as it
// should. All of a sudden a few seconds later, page 2 will get inserted at the beginning of the page
// (before the page 1 content). The update code is actually doing just what it's supposed
// to, it's fetching posts that have the ITEM_UNSEEN bit set. But the reason that page 2 content is being
// returned in an UPDATE is because you hadn't gotten that far yet - you're still on page 1 and everything
// that we loaded for page 1 is now marked as seen. But the stuff on page 2 hasn't been. So... it's being
// treated as "new fresh" content because it is unseen. We need to distinguish it somehow from content
// which "arrived as you were reading page 1". We're going to do this
// by storing in your session the current UTC time whenever you LOAD a network page, and only UPDATE items
// which are both ITEM_UNSEEN and have "changed" since that time. Cross fingers...
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($nouveau && $load) {
// "New Item View" - show all items unthreaded in reverse created date order
$items = q("SELECT item.*, item.id AS item_id, received FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
WHERE true $uids $item_normal
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$simple_update
$sql_extra $sql_nets
ORDER BY item.received DESC $pager_sql "
);
require_once('include/items.php');
xchan_query($items);
$items = fetch_post_tags($items,true);
}
elseif($update) {
// Normal conversation view
if($order === 'post')
$ordering = "created";
else
$ordering = "commented";
if($load) {
// Fetch a page full of parent items for this page
$r = q("SELECT distinct item.id AS item_id, $ordering FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
WHERE true $uids $item_normal
AND item.parent = item.id
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_nets
ORDER BY $ordering DESC $pager_sql "
);
}
else {
// this is an update
$r = q("SELECT item.parent AS item_id FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
WHERE true $uids $item_normal $simple_update
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_nets "
);
$_SESSION['loadtime'] = datetime_convert();
}
// Then fetch all the children of the parents that are on this page
$parents_str = '';
$update_unseen = '';
if($r) {
$parents_str = ids_to_querystr($r,'item_id');
$items = q("SELECT item.*, item.id AS item_id FROM item
WHERE true $uids $item_normal
AND item.parent IN ( %s )
$sql_extra ",
dbesc($parents_str)
);
xchan_query($items,true,(($firehose) ? local_channel() : 0));
$items = fetch_post_tags($items,true);
$items = conv_sort($items,$ordering);
}
else {
$items = array();
}
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 {
if($parents_str) {
$update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )";
}
}
}
if(($update_unseen) && (! $firehose))
$r = q("UPDATE item SET item_unseen = 0 WHERE item_unseen = 1 AND uid = %d $update_unseen ",
intval(local_channel())
);
$mode = (($nouveau) ? 'network-new' : 'network');
$o .= conversation($a,$items,$mode,$update,$page_mode);
if(($items) && (! $update))
$o .= alt_pager($a,count($items));
return $o;
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/permissions.php');
class New_channel extends \Zotlabs\Web\Controller {
function init() {
$cmd = ((argc() > 1) ? argv(1) : '');
if($cmd === 'autofill.json') {
require_once('library/urlify/URLify.php');
$result = array('error' => false, 'message' => '');
$n = trim($_REQUEST['name']);
$x = strtolower(\URLify::transliterate($n));
$test = array();
// first name
if(strpos($x,' '))
$test[] = legal_webbie(substr($x,0,strpos($x,' ')));
if($test[0]) {
// first name plus first initial of last
$test[] = ((strpos($x,' ')) ? $test[0] . legal_webbie(trim(substr($x,strpos($x,' '),2))) : '');
// first name plus random number
$test[] = $test[0] . mt_rand(1000,9999);
}
// fullname
$test[] = legal_webbie($x);
// fullname plus random number
$test[] = legal_webbie($x) . mt_rand(1000,9999);
json_return_and_die(check_webbie($test));
}
if($cmd === 'checkaddr.json') {
require_once('library/urlify/URLify.php');
$result = array('error' => false, 'message' => '');
$n = trim($_REQUEST['nick']);
$x = strtolower(\URLify::transliterate($n));
$test = array();
$n = legal_webbie($x);
if(strlen($n)) {
$test[] = $n;
$test[] = $n . mt_rand(1000,9999);
}
for($y = 0; $y < 100; $y ++)
$test[] = 'id' . mt_rand(1000,9999);
json_return_and_die(check_webbie($test));
}
}
function post() {
$arr = $_POST;
$acc = \App::get_account();
$arr['account_id'] = get_account_id();
// prevent execution by delegated channels as well as those not logged in.
// get_account_id() returns the account_id from the session. But \App::$account
// may point to the original authenticated account.
if((! $acc) || ($acc['account_id'] != $arr['account_id'])) {
notice( t('Permission denied.') . EOL );
return;
}
$result = create_identity($arr);
if(! $result['success']) {
notice($result['message']);
return;
}
$newuid = $result['channel']['channel_id'];
change_channel($result['channel']['channel_id']);
if(! strlen($next_page = get_config('system','workflow_channel_next')))
$next_page = 'settings';
goaway(z_root() . '/' . $next_page);
}
function get() {
$acc = \App::get_account();
if((! $acc) || $acc['account_id'] != get_account_id()) {
notice( t('Permission denied.') . EOL);
return;
}
$default_role = '';
$aid = get_account_id();
if($aid) {
$r = q("select count(channel_id) as total from channel where channel_account_id = %d",
intval($aid)
);
if($r && (! intval($r[0]['total']))) {
$default_role = get_config('system','default_permissions_role');
}
$limit = account_service_class_fetch(get_account_id(),'total_identities');
if($r && ($limit !== false)) {
$channel_usage_message = sprintf( t("You have created %1$.0f of %2$.0f allowed channels."), $r[0]['total'], $limit);
}
else {
$channel_usage_message = '';
}
}
$name = array('name', t('Name or caption'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"'));
$nickhub = '@' . \App::get_hostname();
$nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub));
$privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "" );
$role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel role with your privacy requirements.') . ' <a href="help/roles" target="_blank">' . t('Read more about roles') . '</a>',get_roles());
$o = replace_macros(get_markup_template('new_channel.tpl'), array(
'$title' => t('Create Channel'),
'$desc' => t('A channel is your identity on this network. It can represent a person, a blog, or a forum to name a few. Channels can make connections with other channels to share information with highly detailed permissions.'),
'$label_import' => t('or <a href="import">import an existing channel</a> from another location.'),
'$name' => $name,
'$role' => $role,
'$default_role' => $default_role,
'$nickname' => $nickname,
'$submit' => t('Create'),
'$channel_usage_message' => $channel_usage_message
));
return $o;
}
}

15
Zotlabs/Module/Nojs.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
namespace Zotlabs\Module;
class Nojs extends \Zotlabs\Web\Controller {
function init() {
$n = ((argc() > 1) ? intval(argv(1)) : 1);
setcookie('jsdisabled', $n, 0, '/');
$p = $_GET['redir'];
$hasq = strpos($p,'?');
goaway(z_root() . (($p) ? '/' . $p : '') . (($hasq) ? '' : '?f=' ) . '&jsdisabled=' . $n);
}
}

40
Zotlabs/Module/Notes.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
namespace Zotlabs\Module; /** @file */
class Notes extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
$ret = array('success' => true);
if(array_key_exists('note_text',$_REQUEST)) {
$body = escape_tags($_REQUEST['note_text']);
// I've had my notes vanish into thin air twice in four years.
// Provide a backup copy if there were contents previously
// and there are none being saved now.
if(! $body) {
$old_text = get_pconfig(local_channel(),'notes','text');
if($old_text)
set_pconfig(local_channel(),'notes','text.bak',$old_text);
}
set_pconfig(local_channel(),'notes','text',$body);
}
// push updates to channel clones
if((argc() > 1) && (argv(1) === 'sync')) {
require_once('include/zot.php');
build_sync_packet();
}
logger('notes saved.', LOGGER_DEBUG);
json_return_and_die($ret);
}
}

View File

@@ -0,0 +1,111 @@
<?php
namespace Zotlabs\Module;
class Notifications extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel()) {
goaway(z_root());
}
$request_id = ((\App::$argc > 1) ? \App::$argv[1] : 0);
if($request_id === "all")
return;
if($request_id) {
$r = q("SELECT * FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($request_id),
intval(local_channel())
);
if(count($r)) {
$intro_id = $r[0]['id'];
$contact_id = $r[0]['contact-id'];
}
else {
notice( t('Invalid request identifier.') . EOL);
return;
}
// If it is a friend suggestion, the contact is not a new friend but an existing friend
// that should not be deleted.
$fid = $r[0]['fid'];
if($_POST['submit'] == t('Discard')) {
$r = q("DELETE FROM `intro` WHERE `id` = %d",
intval($intro_id)
);
if(! $fid) {
// The check for blocked and pending is in case the friendship was already approved
// and we just want to get rid of the now pointless notification
$r = q("DELETE FROM `contact` WHERE `id` = %d AND `uid` = %d AND `self` = 0 AND `blocked` = 1 AND `pending` = 1",
intval($contact_id),
intval(local_channel())
);
}
goaway(z_root() . '/notifications/intros');
}
if($_POST['submit'] == t('Ignore')) {
$r = q("UPDATE `intro` SET `ignore` = 1 WHERE `id` = %d",
intval($intro_id));
goaway(z_root() . '/notifications/intros');
}
}
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
nav_set_selected('notifications');
$o = '';
$notif_tpl = get_markup_template('notifications.tpl');
$not_tpl = get_markup_template('notify.tpl');
require_once('include/bbcode.php');
$r = q("SELECT * from notify where uid = %d and seen = 0 order by date desc",
intval(local_channel())
);
if (count($r) > 0) {
$notifications_available =1;
foreach ($r as $it) {
$notif_content .= replace_macros($not_tpl,array(
'$item_link' => z_root().'/notify/view/'. $it['id'],
'$item_image' => $it['photo'],
'$item_text' => strip_tags(bbcode($it['msg'])),
'$item_when' => relative_date($it['date'])
));
}
} else {
$notif_content .= t('No more system notifications.');
}
$o .= replace_macros($notif_tpl,array(
'$notif_header' => t('System Notifications'),
'$notif_link_mark_seen' => t('Mark all system notifications seen'),
'$notif_content' => $notif_content,
'$notifications_available' => $notifications_available,
));
return $o;
}
}

69
Zotlabs/Module/Notify.php Normal file
View File

@@ -0,0 +1,69 @@
<?php
namespace Zotlabs\Module;
class Notify extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
if(argc() > 2 && argv(1) === 'view' && intval(argv(2))) {
$r = q("select * from notify where id = %d and uid = %d limit 1",
intval(argv(2)),
intval(local_channel())
);
if($r) {
q("update notify set seen = 1 where (( parent != '' and parent = '%s' and otype = '%s' ) or link = '%s' ) and uid = %d",
dbesc($r[0]['parent']),
dbesc($r[0]['otype']),
dbesc($r[0]['link']),
intval(local_channel())
);
goaway($r[0]['link']);
}
goaway(z_root());
}
}
function get() {
if(! local_channel())
return login();
$notif_tpl = get_markup_template('notifications.tpl');
$not_tpl = get_markup_template('notify.tpl');
require_once('include/bbcode.php');
$r = q("SELECT * from notify where uid = %d and seen = 0 order by date desc",
intval(local_channel())
);
if($r) {
foreach ($r as $it) {
$notif_content .= replace_macros($not_tpl,array(
'$item_link' => z_root().'/notify/view/'. $it['id'],
'$item_image' => $it['photo'],
'$item_text' => strip_tags(bbcode($it['msg'])),
'$item_when' => relative_date($it['date'])
));
}
}
else {
$notif_content .= t('No more system notifications.');
}
$o .= replace_macros($notif_tpl,array(
'$notif_header' => t('System Notifications'),
'$tabs' => '', // $tabs,
'$notif_content' => $notif_content,
));
return $o;
}
}

36
Zotlabs/Module/Oembed.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
namespace Zotlabs\Module;
require_once("include/oembed.php");
class Oembed extends \Zotlabs\Web\Controller {
function init(){
// logger('mod_oembed ' . \App::$query_string, LOGGER_ALL);
if(argc() > 1) {
if (argv(1) == 'b2h'){
$url = array( "", trim(hex2bin($_REQUEST['url'])));
echo oembed_replacecb($url);
killme();
}
elseif (argv(1) == 'h2b'){
$text = trim(hex2bin($_REQUEST['text']));
echo oembed_html2bbcode($text);
killme();
}
else {
echo "<html><body>";
$src = base64url_decode(argv(1));
$j = oembed_fetch_url($src);
echo $j->html;
// logger('mod-oembed ' . $h, LOGGER_ALL);
echo "</body></html>";
}
}
killme();
}
}

403
Zotlabs/Module/Oep.php Normal file
View File

@@ -0,0 +1,403 @@
<?php
namespace Zotlabs\Module;
// oembed provider
class Oep extends \Zotlabs\Web\Controller {
function init() {
logger('oep: ' . print_r($_REQUEST,true), LOGGER_DEBUG, LOG_INFO);
$html = ((argc() > 1 && argv(1) === 'html') ? true : false);
if($_REQUEST['url']) {
$_REQUEST['url'] = strip_zids($_REQUEST['url']);
$url = $_REQUEST['url'];
}
if(! $url)
http_status_exit(404, 'Not found');
$maxwidth = $_REQUEST['maxwidth'];
$maxheight = $_REQUEST['maxheight'];
$format = $_REQUEST['format'];
if($format && $format !== 'json')
http_status_exit(501, 'Not implemented');
if(fnmatch('*/photos/*/album/*',$url))
$arr = $this->oep_album_reply($_REQUEST);
elseif(fnmatch('*/photos/*/image/*',$url))
$arr = $this->oep_photo_reply($_REQUEST);
elseif(fnmatch('*/photos*',$url))
$arr = $this->oep_phototop_reply($_REQUEST);
elseif(fnmatch('*/display/*',$url))
$arr = $this->oep_display_reply($_REQUEST);
elseif(fnmatch('*/channel/*mid=*',$url))
$arr = $this->oep_mid_reply($_REQUEST);
elseif(fnmatch('*/channel*',$url))
$arr = $this->oep_profile_reply($_REQUEST);
elseif(fnmatch('*/profile/*',$url))
$arr = $this->oep_profile_reply($_REQUEST);
if($arr) {
if($html) {
if($arr['type'] === 'rich') {
header('Content-Type: text/html');
echo $arr['html'];
}
}
else {
header('Content-Type: application/json+oembed');
echo json_encode($arr);
}
killme();
}
http_status_exit(404,'Not found');
}
function oep_display_reply($args) {
$ret = array();
$url = $args['url'];
$maxwidth = intval($args['maxwidth']);
$maxheight = intval($args['maxheight']);
if(preg_match('#//(.*?)/(.*?)/(.*?)/(.*?)mid\=(.*?)(&|$)#',$url,$matches)) {
$chn = $matches[3];
$res = $matches[5];
}
if(! ($chn && $res))
return;
$c = q("select * from channel where channel_address = '%s' limit 1",
dbesc($chn)
);
if(! $c)
return;
$sql_extra = item_permissions_sql($c[0]['channel_id']);
$p = q("select * from item where mid = '%s' and uid = %d $sql_extra limit 1",
dbesc($res),
intval($c[0]['channel_id'])
);
if(! $p)
return;
xchan_query($p,true);
$p = fetch_post_tags($p,true);
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
if($p[0]['title'])
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
$o .= $p[0]['body'];
$o .= "[/share]";
$o = bbcode($o);
$ret['type'] = 'rich';
$w = (($maxwidth) ? $maxwidth : 640);
$h = (($maxheight) ? $maxheight : $w * 2 / 3);
$ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>';
$ret['width'] = $w;
$ret['height'] = $h;
return $ret;
}
function oep_mid_reply($args) {
$ret = array();
$url = $args['url'];
$maxwidth = intval($args['maxwidth']);
$maxheight = intval($args['maxheight']);
if(preg_match('#//(.*?)/(.*?)/(.*?)/(.*?)mid\=(.*?)(&|$)#',$url,$matches)) {
$chn = $matches[3];
$res = $matches[5];
}
if(! ($chn && $res))
return;
$c = q("select * from channel where channel_address = '%s' limit 1",
dbesc($chn)
);
if(! $c)
return;
$sql_extra = item_permissions_sql($c[0]['channel_id']);
$p = q("select * from item where mid = '%s' and uid = %d $sql_extra limit 1",
dbesc($res),
intval($c[0]['channel_id'])
);
if(! $p)
return;
xchan_query($p,true);
$p = fetch_post_tags($p,true);
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
if($p[0]['title'])
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
$o .= $p[0]['body'];
$o .= "[/share]";
$o = bbcode($o);
$ret['type'] = 'rich';
$w = (($maxwidth) ? $maxwidth : 640);
$h = (($maxheight) ? $maxheight : $w * 2 / 3);
$ret['html'] = '<div style="width: ' . $w . '; height: ' . $h . '; font-family: sans-serif,arial,freesans;" >' . $o . '</div>';
$ret['width'] = $w;
$ret['height'] = $h;
return $ret;
}
function oep_profile_reply($args) {
require_once('include/identity.php');
require_once('include/Contact.php');
$url = $args['url'];
if(preg_match('#//(.*?)/(.*?)/(.*?)(/|\?|&|$)#',$url,$matches)) {
$chn = $matches[3];
}
if(! $chn)
return;
$c = channelx_by_nick($chn);
if(! $c)
return;
$maxwidth = intval($args['maxwidth']);
$maxheight = intval($args['maxheight']);
$width = 800;
$height = 375;
if($maxwidth) {
$width = $maxwidth;
$height = (375 / 800) * $width;
}
if($maxheight) {
if($maxheight < $height) {
$width = (800 / 375) * $maxheight;
$height = $maxheight;
}
}
$ret = array();
$ret['type'] = 'rich';
$ret['width'] = intval($width);
$ret['height'] = intval($height);
$ret['html'] = get_zcard_embed($c,get_observer_hash(),array('width' => $width, 'height' => $height));
return $ret;
}
function oep_album_reply($args) {
$ret = array();
$url = $args['url'];
$maxwidth = intval($args['maxwidth']);
$maxheight = intval($args['maxheight']);
if(preg_match('|//(.*?)/(.*?)/(.*?)/album/|',$url,$matches)) {
$chn = $matches[3];
$res = hex2bin(basename($url));
}
if(! ($chn && $res))
return;
$c = q("select * from channel where channel_address = '%s' limit 1",
dbesc($chn)
);
if(! $c)
return;
$sql_extra = permissions_sql($c[0]['channel_id']);
$p = q("select resource_id from photo where album = '%s' and uid = %d and scale = 0 $sql_extra order by created desc limit 1",
dbesc($res),
intval($c[0]['channel_id'])
);
if(! $p)
return;
$res = $p[0]['resource_id'];
$r = q("select height, width, scale, resource_id from photo where uid = %d and resource_id = '%s' $sql_extra order by scale asc",
intval($c[0]['channel_id']),
dbesc($res)
);
if($r) {
foreach($r as $rr) {
$foundres = false;
if($maxheight && $rr['height'] > $maxheight)
continue;
if($maxwidth && $rr['width'] > $maxwidth)
continue;
$foundres = true;
break;
}
if($foundres) {
$ret['type'] = 'link';
$ret['thumbnail_url'] = z_root() . '/photo/' . '/' . $rr['resource_id'] . '-' . $rr['scale'];
$ret['thumbnail_width'] = $rr['width'];
$ret['thumbnail_height'] = $rr['height'];
}
}
return $ret;
}
function oep_phototop_reply($args) {
$ret = array();
$url = $args['url'];
$maxwidth = intval($args['maxwidth']);
$maxheight = intval($args['maxheight']);
if(preg_match('|//(.*?)/(.*?)/(.*?)$|',$url,$matches)) {
$chn = $matches[3];
}
if(! $chn)
return;
$c = q("select * from channel where channel_address = '%s' limit 1",
dbesc($chn)
);
if(! $c)
return;
$sql_extra = permissions_sql($c[0]['channel_id']);
$p = q("select resource_id from photo where uid = %d and scale = 0 $sql_extra order by created desc limit 1",
intval($c[0]['channel_id'])
);
if(! $p)
return;
$res = $p[0]['resource_id'];
$r = q("select height, width, scale, resource_id from photo where uid = %d and resource_id = '%s' $sql_extra order by scale asc",
intval($c[0]['channel_id']),
dbesc($res)
);
if($r) {
foreach($r as $rr) {
$foundres = false;
if($maxheight && $rr['height'] > $maxheight)
continue;
if($maxwidth && $rr['width'] > $maxwidth)
continue;
$foundres = true;
break;
}
if($foundres) {
$ret['type'] = 'link';
$ret['thumbnail_url'] = z_root() . '/photo/' . '/' . $rr['resource_id'] . '-' . $rr['scale'];
$ret['thumbnail_width'] = $rr['width'];
$ret['thumbnail_height'] = $rr['height'];
}
}
return $ret;
}
function oep_photo_reply($args) {
$ret = array();
$url = $args['url'];
$maxwidth = intval($args['maxwidth']);
$maxheight = intval($args['maxheight']);
if(preg_match('|//(.*?)/(.*?)/(.*?)/image/|',$url,$matches)) {
$chn = $matches[3];
$res = basename($url);
}
if(! ($chn && $res))
return;
$c = q("select * from channel where channel_address = '%s' limit 1",
dbesc($chn)
);
if(! $c)
return;
$sql_extra = permissions_sql($c[0]['channel_id']);
$r = q("select height, width, scale, resource_id from photo where uid = %d and resource_id = '%s' $sql_extra order by scale asc",
intval($c[0]['channel_id']),
dbesc($res)
);
if($r) {
foreach($r as $rr) {
$foundres = false;
if($maxheight && $rr['height'] > $maxheight)
continue;
if($maxwidth && $rr['width'] > $maxwidth)
continue;
$foundres = true;
break;
}
if($foundres) {
$ret['type'] = 'link';
$ret['thumbnail_url'] = z_root() . '/photo/' . '/' . $rr['resource_id'] . '-' . $rr['scale'];
$ret['thumbnail_width'] = $rr['width'];
$ret['thumbnail_height'] = $rr['height'];
}
}
return $ret;
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace Zotlabs\Module;
class Oexchange extends \Zotlabs\Web\Controller {
function init() {
if((argc() > 1) && (argv(1) === 'xrd')) {
$tpl = get_markup_template('oexchange_xrd.tpl');
$o = replace_macros($tpl, array('$base' => z_root()));
echo $o;
killme();
}
}
function get() {
if(! local_channel()) {
if(remote_channel()) {
$observer = \App::get_observer();
if($observer && $observer['xchan_url']) {
$parsed = @parse_url($observer['xchan_url']);
if(! $parsed) {
notice( t('Unable to find your hub.') . EOL);
return;
}
$url = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '');
$url .= '/oexchange';
$result = z_post_url($url,$_REQUEST);
json_return_and_die($result);
}
}
return login(false);
}
if((argc() > 1) && argv(1) === 'done') {
info( t('Post successful.') . EOL);
return;
}
$url = (((x($_REQUEST,'url')) && strlen($_REQUEST['url']))
? urlencode(notags(trim($_REQUEST['url']))) : '');
$title = (((x($_REQUEST,'title')) && strlen($_REQUEST['title']))
? '&title=' . urlencode(notags(trim($_REQUEST['title']))) : '');
$description = (((x($_REQUEST,'description')) && strlen($_REQUEST['description']))
? '&description=' . urlencode(notags(trim($_REQUEST['description']))) : '');
$tags = (((x($_REQUEST,'tags')) && strlen($_REQUEST['tags']))
? '&tags=' . urlencode(notags(trim($_REQUEST['tags']))) : '');
$ret = z_fetch_url(z_root() . '/urlinfo?f=&url=' . $url . $title . $description . $tags);
if($ret['success'])
$s = $ret['body'];
if(! strlen($s))
return;
$post = array();
$post['profile_uid'] = local_channel();
$post['return'] = '/oexchange/done' ;
$post['body'] = $s;
$post['type'] = 'wall';
$_REQUEST = $post;
$mod = new Item();
$mod->post();
}
}

17
Zotlabs/Module/Online.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
namespace Zotlabs\Module; /** @file */
class Online extends \Zotlabs\Web\Controller {
function init() {
$ret = array('result' => false);
if(argc() != 2)
json_return_and_die($ret);
$ret = get_online_status(argv(1));
json_return_and_die($ret);
}
}

198
Zotlabs/Module/Openid.php Normal file
View File

@@ -0,0 +1,198 @@
<?php
namespace Zotlabs\Module;
require_once('library/openid/openid.php');
require_once('include/auth.php');
class Openid extends \Zotlabs\Web\Controller {
function get() {
$noid = get_config('system','disable_openid');
if($noid)
goaway(z_root());
logger('mod_openid ' . print_r($_REQUEST,true), LOGGER_DATA);
if(x($_REQUEST,'openid_mode')) {
$openid = new LightOpenID(z_root());
if($openid->validate()) {
logger('openid: validate');
$authid = normalise_openid($_REQUEST['openid_identity']);
if(! strlen($authid)) {
logger( t('OpenID protocol error. No ID returned.') . EOL);
goaway(z_root());
}
$x = match_openid($authid);
if($x) {
$r = q("select * from channel where channel_id = %d limit 1",
intval($x)
);
if($r) {
$y = q("select * from account where account_id = %d limit 1",
intval($r[0]['channel_account_id'])
);
if($y) {
foreach($y as $record) {
if(($record['account_flags'] == ACCOUNT_OK) || ($record['account_flags'] == ACCOUNT_UNVERIFIED)) {
logger('mod_openid: openid success for ' . $x[0]['channel_name']);
$_SESSION['uid'] = $r[0]['channel_id'];
$_SESSION['account_id'] = $r[0]['channel_account_id'];
$_SESSION['authenticated'] = true;
authenticate_success($record,true,true,true,true);
goaway(z_root());
}
}
}
}
}
// Successful OpenID login - but we can't match it to an existing account.
// See if they've got an xchan
$r = q("select * from xconfig left join xchan on xchan_hash = xconfig.xchan where cat = 'system' and k = 'openid' and v = '%s' limit 1",
dbesc($authid)
);
if($r) {
$_SESSION['authenticated'] = 1;
$_SESSION['visitor_id'] = $r[0]['xchan_hash'];
$_SESSION['my_url'] = $r[0]['xchan_url'];
$_SESSION['my_address'] = $r[0]['xchan_addr'];
$arr = array('xchan' => $r[0], 'session' => $_SESSION);
call_hooks('magic_auth_openid_success',$arr);
\App::set_observer($r[0]);
require_once('include/security.php');
\App::set_groups(init_groups_visitor($_SESSION['visitor_id']));
info(sprintf( t('Welcome %s. Remote authentication successful.'),$r[0]['xchan_name']));
logger('mod_openid: remote auth success from ' . $r[0]['xchan_addr']);
if($_SESSION['return_url'])
goaway($_SESSION['return_url']);
goaway(z_root());
}
// no xchan...
// create one.
// We should probably probe the openid url and figure out if they have any kind of social presence we might be able to
// scrape some identifying info from.
$name = $authid;
$url = trim($_REQUEST['openid_identity'],'/');
if(strpos($url,'http') === false)
$url = 'https://' . $url;
$pphoto = z_root() . '/' . get_default_profile_photo();
$parsed = @parse_url($url);
if($parsed) {
$host = $parsed['host'];
}
$attr = $openid->getAttributes();
if(is_array($attr) && count($attr)) {
foreach($attr as $k => $v) {
if($k === 'namePerson/friendly')
$nick = notags(trim($v));
if($k === 'namePerson/first')
$first = notags(trim($v));
if($k === 'namePerson')
$name = notags(trim($v));
if($k === 'contact/email')
$addr = notags(trim($v));
if($k === 'media/image/aspect11')
$photosq = trim($v);
if($k === 'media/image/default')
$photo_other = trim($v);
}
}
if(! $nick) {
if($first)
$nick = $first;
else
$nick = $name;
}
require_once('library/urlify/URLify.php');
$x = strtolower(\URLify::transliterate($nick));
if($nick & $host)
$addr = $nick . '@' . $host;
$network = 'unknown';
if($photosq)
$pphoto = $photosq;
elseif($photo_other)
$pphoto = $photo_other;
$mimetype = guess_image_type($pphoto);
$x = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_mimetype,
xchan_photo_l, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_photo_date,
xchan_name_date, xchan_hidden)
values ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 1) ",
dbesc($url),
dbesc(''),
dbesc(''),
dbesc(''),
dbesc($mimetype),
dbesc($pphoto),
dbesc($addr),
dbesc($url),
dbesc(''),
dbesc(''),
dbesc(''),
dbesc($name),
dbesc($network),
dbesc(datetime_convert()),
dbesc(datetime_convert())
);
if($x) {
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($url)
);
if($r) {
$photos = import_xchan_photo($pphoto,$url);
if($photos) {
$z = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s',
xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
dbesc($photos[3]),
dbesc($url)
);
}
set_xconfig($url,'system','openid',$authid);
$_SESSION['authenticated'] = 1;
$_SESSION['visitor_id'] = $r[0]['xchan_hash'];
$_SESSION['my_url'] = $r[0]['xchan_url'];
$_SESSION['my_address'] = $r[0]['xchan_addr'];
$arr = array('xchan' => $r[0], 'session' => $_SESSION);
call_hooks('magic_auth_openid_success',$arr);
\App::set_observer($r[0]);
info(sprintf( t('Welcome %s. Remote authentication successful.'),$r[0]['xchan_name']));
logger('mod_openid: remote auth success from ' . $r[0]['xchan_addr']);
if($_SESSION['return_url'])
goaway($_SESSION['return_url']);
goaway(z_root());
}
}
}
}
notice( t('Login failed.') . EOL);
goaway(z_root());
// NOTREACHED
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Zotlabs\Module;
class Opensearch extends \Zotlabs\Web\Controller {
function init() {
$tpl = get_markup_template('opensearch.tpl');
header("Content-type: application/opensearchdescription+xml");
$o = replace_macros($tpl, array(
'$baseurl' => z_root(),
'$nodename' => \App::get_hostname(),
));
echo $o;
killme();
}
}

150
Zotlabs/Module/Page.php Normal file
View File

@@ -0,0 +1,150 @@
<?php
namespace Zotlabs\Module;
require_once('include/items.php');
require_once('include/conversation.php');
require_once('include/page_widgets.php');
class Page extends \Zotlabs\Web\Controller {
function init() {
// We need this to make sure the channel theme is always loaded.
$which = argv(1);
$profile = 0;
profile_load($a,$which,$profile);
if(\App::$profile['profile_uid'])
head_set_icon(\App::$profile['thumb']);
// load the item here in the init function because we need to extract
// the page layout and initialise the correct theme.
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
// perm_is_allowed is denied unconditionally when 'site blocked to unauthenticated members'.
// This bypasses that restriction for sys channel (public) content
if((! perm_is_allowed(\App::$profile['profile_uid'],$ob_hash,'view_pages')) && (! is_sys_channel(\App::$profile['profile_uid']))) {
notice( t('Permission denied.') . EOL);
return;
}
if(argc() < 3) {
notice( t('Invalid item.') . EOL);
return;
}
$channel_address = argv(1);
// The page link title was stored in a urlencoded format
// php or the browser may/will have decoded it, so re-encode it for our search
$page_id = urlencode(argv(2));
$u = q("select channel_id from channel where channel_address = '%s' limit 1",
dbesc($channel_address)
);
if(! $u) {
notice( t('Channel not found.') . EOL);
return;
}
if($_REQUEST['rev'])
$revision = " and revision = " . intval($_REQUEST['rev']) . " ";
else
$revision = " order by revision desc ";
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 item.item_delayed = 0 and (( service = 'WEBPAGE' and item_type = %d )
OR ( service = 'PDL' AND item_type = %d )) $sql_options $revision limit 1",
intval($u[0]['channel_id']),
dbesc($page_id),
intval(ITEM_TYPE_WEBPAGE),
intval(ITEM_TYPE_PDL)
);
if(! $r) {
// 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 item.item_delayed = 0 and service = 'WEBPAGE' and
item_type = %d $revision limit 1",
intval($u[0]['channel_id']),
dbesc($page_id),
intval(ITEM_TYPE_WEBPAGE)
);
if($x) {
// Yes, it's there. You just aren't allowed to see it.
notice( t('Permission denied.') . EOL);
}
else {
notice( t('Page not found.') . EOL);
}
return;
}
if($r[0]['title'])
\App::$page['title'] = escape_tags($r[0]['title']);
if($r[0]['item_type'] == ITEM_TYPE_PDL) {
\App::$comanche = new \Zotlabs\Render\Comanche();
\App::$comanche->parse($r[0]['body']);
\App::$pdl = $r[0]['body'];
}
elseif($r[0]['layout_mid']) {
$l = q("select body from item where mid = '%s' and uid = %d limit 1",
dbesc($r[0]['layout_mid']),
intval($u[0]['channel_id'])
);
if($l) {
\App::$comanche = new \Zotlabs\Render\Comanche();
\App::$comanche->parse($l[0]['body']);
\App::$pdl = $l[0]['body'];
}
}
\App::$data['webpage'] = $r;
}
function get() {
$r = \App::$data['webpage'];
if(! $r)
return;
if($r[0]['item_type'] == ITEM_TYPE_PDL) {
$r[0]['body'] = t('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.');
$r[0]['mimetype'] = 'text/plain';
$r[0]['title'] = '';
}
xchan_query($r);
$r = fetch_post_tags($r,true);
if($r[0]['mimetype'] === 'application/x-pdl')
\App::$page['pdl_content'] = true;
$o .= prepare_page($r[0]);
return $o;
}
}

122
Zotlabs/Module/Pconfig.php Normal file
View File

@@ -0,0 +1,122 @@
<?php
namespace Zotlabs\Module;
class Pconfig extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
if($_SESSION['delegate'])
return;
check_form_security_token_redirectOnErr('/pconfig', 'pconfig');
$cat = trim(escape_tags($_POST['cat']));
$k = trim(escape_tags($_POST['k']));
$v = trim($_POST['v']);
if(in_array(argv(2),$this->disallowed_pconfig())) {
notice( t('This setting requires special processing and editing has been blocked.') . EOL);
return;
}
if(strpos($k,'password') !== false) {
$v = z_obscure($v);
}
set_pconfig(local_channel(),$cat,$k,$v);
build_sync_packet();
goaway(z_root() . '/pconfig/' . $cat . '/' . $k);
}
function get() {
if(! local_channel()) {
return login();
}
$content = '<h3>' . t('Configuration Editor') . '</h3>';
$content .= '<div class="descriptive-paragraph">' . t('Warning: Changing some settings could render your channel inoperable. Please leave this page unless you are comfortable with and knowledgeable about how to correctly use this feature.') . '</div>' . EOL . EOL;
if(argc() == 3) {
$content .= '<a href="pconfig">pconfig[' . local_channel() . ']</a>' . EOL;
$content .= '<a href="pconfig/' . escape_tags(argv(1)) . '">pconfig[' . local_channel() . '][' . escape_tags(argv(1)) . ']</a>' . EOL . EOL;
$content .= '<a href="pconfig/' . escape_tags(argv(1)) . '/' . escape_tags(argv(2)) . '" >pconfig[' . local_channel() . '][' . escape_tags(argv(1)) . '][' . escape_tags(argv(2)) . ']</a> = ' . get_pconfig(local_channel(),escape_tags(argv(1)),escape_tags(argv(2))) . EOL;
if(in_array(argv(2),$this->disallowed_pconfig())) {
notice( t('This setting requires special processing and editing has been blocked.') . EOL);
return $content;
}
else
$content .= $this->pconfig_form(escape_tags(argv(1)),escape_tags(argv(2)));
}
if(argc() == 2) {
$content .= '<a href="pconfig">pconfig[' . local_channel() . ']</a>' . EOL;
load_pconfig(local_channel(),escape_tags(argv(1)));
foreach(\App::$config[local_channel()][escape_tags(argv(1))] as $k => $x) {
$content .= '<a href="pconfig/' . escape_tags(argv(1)) . '/' . $k . '" >pconfig[' . local_channel() . '][' . escape_tags(argv(1)) . '][' . $k . ']</a> = ' . escape_tags($x) . EOL;
}
}
if(argc() == 1) {
$r = q("select * from pconfig where uid = " . local_channel());
if($r) {
foreach($r as $rr) {
$content .= '<a href="' . 'pconfig/' . escape_tags($rr['cat']) . '/' . escape_tags($rr['k']) . '" >pconfig[' . local_channel() . '][' . escape_tags($rr['cat']) . '][' . escape_tags($rr['k']) . ']</a> = ' . escape_tags($rr['v']) . EOL;
}
}
}
return $content;
}
function pconfig_form($cat,$k) {
$o = '<form action="pconfig" method="post" >';
$o .= '<input type="hidden" name="form_security_token" value="' . get_form_security_token('pconfig') . '" />';
$v = get_pconfig(local_channel(),$cat,$k);
if(strpos($k,'password') !== false)
$v = z_unobscure($v);
$o .= '<input type="hidden" name="cat" value="' . $cat . '" />';
$o .= '<input type="hidden" name="k" value="' . $k . '" />';
if(strpos($v,"\n"))
$o .= '<textarea name="v" >' . escape_tags($v) . '</textarea>';
else
$o .= '<input type="text" name="v" value="' . escape_tags($v) . '" />';
$o .= EOL . EOL;
$o .= '<input type="submit" name="submit" value="' . t('Submit') . '" />';
$o .= '</form>';
return $o;
}
function disallowed_pconfig() {
return array(
'permissions_role'
);
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Zotlabs\Module;
class Pdledit extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
if(! $_REQUEST['module'])
return;
if(! trim($_REQUEST['content'])) {
del_pconfig(local_channel(),'system','mod_' . $_REQUEST['module'] . '.pdl');
goaway(z_root() . '/pdledit/' . $_REQUEST['module']);
}
set_pconfig(local_channel(),'system','mod_' . $_REQUEST['module'] . '.pdl',escape_tags($_REQUEST['content']));
build_sync_packet();
info( t('Layout updated.') . EOL);
goaway(z_root() . '/pdledit/' . $_REQUEST['module']);
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if(argc() > 1)
$module = 'mod_' . argv(1) . '.pdl';
else {
$o .= '<div class="generic-content-wrapper-styled">';
$o .= '<h1>' . t('Edit System Page Description') . '</h1>';
$files = glob('mod/*');
if($files) {
foreach($files as $f) {
$name = basename($f,'.php');
$x = theme_include('mod_' . $name . '.pdl');
if($x) {
$o .= '<a href="pdledit/' . $name . '" >' . $name . '</a><br />';
}
}
}
$o .= '</div>';
// list module pdl files
return $o;
}
$t = get_pconfig(local_channel(),'system',$module);
if(! $t)
$t = file_get_contents(theme_include($module));
if(! $t) {
notice( t('Layout not found.') . EOL);
return '';
}
$o = replace_macros(get_markup_template('pdledit.tpl'),array(
'$header' => t('Edit System Page Description'),
'$mname' => t('Module Name:'),
'$help' => t('Layout Help'),
'$module' => argv(1),
'$content' => htmlspecialchars($t,ENT_COMPAT,'UTF-8'),
'$submit' => t('Submit')
));
return $o;
}
}

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