aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Zotlabs/Extend/Hook.php76
-rw-r--r--Zotlabs/Module/Achievements.php93
-rw-r--r--Zotlabs/Module/Acl.php314
-rw-r--r--Zotlabs/Module/Admin.php1786
-rw-r--r--Zotlabs/Module/Api.php122
-rw-r--r--Zotlabs/Module/Appman.php108
-rw-r--r--Zotlabs/Module/Apps.php46
-rw-r--r--Zotlabs/Module/Attach.php61
-rw-r--r--Zotlabs/Module/Authtest.php61
-rw-r--r--Zotlabs/Module/Block.php92
-rw-r--r--Zotlabs/Module/Blocks.php172
-rw-r--r--Zotlabs/Module/Bookmarks.php105
-rw-r--r--Zotlabs/Module/Branchtopic.php47
-rw-r--r--Zotlabs/Module/Cal.php357
-rw-r--r--Zotlabs/Module/Channel.php (renamed from mod/channel.php)90
-rw-r--r--Zotlabs/Module/Chanview.php110
-rw-r--r--Zotlabs/Module/Chat.php261
-rw-r--r--Zotlabs/Module/Chatsvc.php168
-rw-r--r--Zotlabs/Module/Cloud.php110
-rw-r--r--Zotlabs/Module/Common.php73
-rw-r--r--Zotlabs/Module/Connect.php130
-rw-r--r--Zotlabs/Module/Connections.php324
-rw-r--r--Zotlabs/Module/Connedit.php762
-rw-r--r--Zotlabs/Module/Contactgroup.php54
-rw-r--r--Zotlabs/Module/Cover_photo.php423
-rw-r--r--Zotlabs/Module/Dav.php150
-rw-r--r--Zotlabs/Module/Directory.php425
-rw-r--r--Zotlabs/Module/Dirsearch.php462
-rw-r--r--Zotlabs/Module/Display.php346
-rw-r--r--Zotlabs/Module/Dreport.php145
-rw-r--r--Zotlabs/Module/Editblock.php198
-rw-r--r--Zotlabs/Module/Editlayout.php195
-rw-r--r--Zotlabs/Module/Editpost.php181
-rw-r--r--Zotlabs/Module/Editwebpage.php239
-rw-r--r--Zotlabs/Module/Events.php714
-rw-r--r--Zotlabs/Module/Fbrowser.php136
-rw-r--r--Zotlabs/Module/Feed.php48
-rw-r--r--Zotlabs/Module/Ffsapi.php71
-rw-r--r--Zotlabs/Module/Fhublocs.php85
-rw-r--r--Zotlabs/Module/Filer.php61
-rw-r--r--Zotlabs/Module/Filerm.php39
-rw-r--r--Zotlabs/Module/Filestorage.php173
-rw-r--r--Zotlabs/Module/Follow.php65
-rw-r--r--Zotlabs/Module/Fsuggest.php117
-rw-r--r--Zotlabs/Module/Getfile.php102
-rw-r--r--Zotlabs/Module/Group.php244
-rw-r--r--Zotlabs/Module/Hcard.php60
-rw-r--r--Zotlabs/Module/Help.php146
-rw-r--r--Zotlabs/Module/Home.php89
-rw-r--r--Zotlabs/Module/Hostxrd.php24
-rw-r--r--Zotlabs/Module/Id.php319
-rw-r--r--Zotlabs/Module/Impel.php207
-rw-r--r--Zotlabs/Module/Import.php553
-rw-r--r--Zotlabs/Module/Import_items.php129
-rw-r--r--Zotlabs/Module/Invite.php152
-rw-r--r--Zotlabs/Module/Item.php1265
-rw-r--r--Zotlabs/Module/Lang.php12
-rw-r--r--Zotlabs/Module/Layouts.php199
-rw-r--r--Zotlabs/Module/Like.php547
-rw-r--r--Zotlabs/Module/Linkinfo.php381
-rw-r--r--Zotlabs/Module/Lockview.php121
-rw-r--r--Zotlabs/Module/Locs.php132
-rw-r--r--Zotlabs/Module/Login.php13
-rw-r--r--Zotlabs/Module/Lostpass.php138
-rw-r--r--Zotlabs/Module/Magic.php173
-rw-r--r--Zotlabs/Module/Mail.php397
-rw-r--r--Zotlabs/Module/Manage.php181
-rw-r--r--Zotlabs/Module/Match.php84
-rw-r--r--Zotlabs/Module/Menu.php173
-rw-r--r--Zotlabs/Module/Message.php110
-rw-r--r--Zotlabs/Module/Mitem.php245
-rw-r--r--Zotlabs/Module/Mood.php146
-rw-r--r--Zotlabs/Module/Msearch.php47
-rw-r--r--Zotlabs/Module/Network.php531
-rw-r--r--Zotlabs/Module/New_channel.php151
-rw-r--r--Zotlabs/Module/Nojs.php15
-rw-r--r--Zotlabs/Module/Notes.php40
-rw-r--r--Zotlabs/Module/Notifications.php111
-rw-r--r--Zotlabs/Module/Notify.php69
-rw-r--r--Zotlabs/Module/Oembed.php36
-rw-r--r--Zotlabs/Module/Oep.php403
-rw-r--r--Zotlabs/Module/Oexchange.php77
-rw-r--r--Zotlabs/Module/Online.php17
-rw-r--r--Zotlabs/Module/Openid.php198
-rw-r--r--Zotlabs/Module/Opensearch.php24
-rw-r--r--Zotlabs/Module/Page.php150
-rw-r--r--Zotlabs/Module/Pconfig.php122
-rw-r--r--Zotlabs/Module/Pdledit.php72
-rw-r--r--Zotlabs/Module/Photo.php250
-rw-r--r--Zotlabs/Module/Photos.php1384
-rw-r--r--Zotlabs/Module/Ping.php497
-rw-r--r--Zotlabs/Module/Poco.php13
-rw-r--r--Zotlabs/Module/Poke.php194
-rw-r--r--Zotlabs/Module/Post.php36
-rw-r--r--Zotlabs/Module/Prate.php105
-rw-r--r--Zotlabs/Module/Pretheme.php28
-rw-r--r--Zotlabs/Module/Probe.php47
-rw-r--r--Zotlabs/Module/Profile.php90
-rw-r--r--Zotlabs/Module/Profile_photo.php436
-rw-r--r--Zotlabs/Module/Profiles.php795
-rw-r--r--Zotlabs/Module/Profperm.php172
-rw-r--r--Zotlabs/Module/Pubsites.php59
-rw-r--r--Zotlabs/Module/Pubstream.php168
-rw-r--r--Zotlabs/Module/Randprof.php18
-rw-r--r--Zotlabs/Module/Rate.php178
-rw-r--r--Zotlabs/Module/Ratings.php115
-rw-r--r--Zotlabs/Module/Ratingsearch.php76
-rw-r--r--Zotlabs/Module/Rbmark.php121
-rw-r--r--Zotlabs/Module/Regdir.php109
-rw-r--r--Zotlabs/Module/Register.php270
-rw-r--r--Zotlabs/Module/Regmod.php40
-rw-r--r--Zotlabs/Module/Regver.php28
-rw-r--r--Zotlabs/Module/Removeaccount.php72
-rw-r--r--Zotlabs/Module/Removeme.php72
-rw-r--r--Zotlabs/Module/Rmagic.php95
-rw-r--r--Zotlabs/Module/Rpost.php144
-rw-r--r--Zotlabs/Module/Rsd_xml.php17
-rw-r--r--Zotlabs/Module/Search.php228
-rw-r--r--Zotlabs/Module/Search_ac.php82
-rw-r--r--Zotlabs/Module/Service_limits.php28
-rw-r--r--Zotlabs/Module/Settings.php1150
-rw-r--r--Zotlabs/Module/Setup.php754
-rw-r--r--Zotlabs/Module/Share.php93
-rw-r--r--Zotlabs/Module/Sharedwithme.php113
-rw-r--r--Zotlabs/Module/Siteinfo.php94
-rw-r--r--Zotlabs/Module/Siteinfo_json.php14
-rw-r--r--Zotlabs/Module/Sitelist.php67
-rw-r--r--Zotlabs/Module/Smilies.php21
-rw-r--r--Zotlabs/Module/Sources.php173
-rw-r--r--Zotlabs/Module/Sslify.php30
-rw-r--r--Zotlabs/Module/Starred.php39
-rw-r--r--Zotlabs/Module/Subthread.php169
-rw-r--r--Zotlabs/Module/Suggest.php72
-rw-r--r--Zotlabs/Module/Tagger.php140
-rw-r--r--Zotlabs/Module/Tagrm.php147
-rw-r--r--Zotlabs/Module/Tasks.php112
-rw-r--r--Zotlabs/Module/Thing.php368
-rw-r--r--Zotlabs/Module/Toggle_mobile.php23
-rw-r--r--Zotlabs/Module/Toggle_safesearch.php31
-rw-r--r--Zotlabs/Module/Uexport.php71
-rw-r--r--Zotlabs/Module/Update_channel.php (renamed from mod/update_channel.php)11
-rw-r--r--Zotlabs/Module/Update_display.php48
-rw-r--r--Zotlabs/Module/Update_home.php42
-rw-r--r--Zotlabs/Module/Update_network.php44
-rw-r--r--Zotlabs/Module/Update_pubstream.php42
-rw-r--r--Zotlabs/Module/Update_search.php69
-rw-r--r--Zotlabs/Module/View.php20
-rw-r--r--Zotlabs/Module/Viewconnections.php117
-rw-r--r--Zotlabs/Module/Viewsrc.php53
-rw-r--r--Zotlabs/Module/Wall_attach.php55
-rw-r--r--Zotlabs/Module/Wall_upload.php57
-rw-r--r--Zotlabs/Module/Webfinger.php54
-rw-r--r--Zotlabs/Module/Webpages.php207
-rw-r--r--Zotlabs/Module/Well_known.php69
-rw-r--r--Zotlabs/Module/Wfinger.php140
-rw-r--r--Zotlabs/Module/Xchan.php47
-rw-r--r--Zotlabs/Module/Xpoco.php13
-rw-r--r--Zotlabs/Module/Xrd.php81
-rw-r--r--Zotlabs/Module/Xref.php26
-rw-r--r--Zotlabs/Module/Zfinger.php18
-rw-r--r--Zotlabs/Module/Zotfeed.php52
-rw-r--r--Zotlabs/Module/Zping.php33
-rw-r--r--Zotlabs/Web/CheckJS.php13
-rw-r--r--Zotlabs/Web/Controller.php12
-rw-r--r--Zotlabs/Web/Router.php117
-rwxr-xr-xboot.php6
-rw-r--r--doc/context/channel/help.html24
-rw-r--r--doc/context/cloud/help.html22
-rw-r--r--doc/context/en/admin/security/help.html (renamed from doc/context/admin/security/help.html)0
-rw-r--r--doc/context/en/channel/help.html8
-rw-r--r--doc/context/en/cloud/help.html6
-rw-r--r--doc/context/en/mail/help.html (renamed from doc/context/mail/help.html)0
-rw-r--r--doc/context/en/network/help.html (renamed from doc/context/network/help.html)20
-rw-r--r--doc/context/en/photos/help.html6
-rw-r--r--doc/context/en/profile/help.html6
-rw-r--r--doc/context/photos/help.html22
-rw-r--r--doc/context/profile/help.html22
-rw-r--r--doc/plugins.bb68
-rw-r--r--include/api.php39
-rw-r--r--include/bb2diaspora.php34
-rw-r--r--include/help.php150
-rwxr-xr-xinclude/importdoc.php2
-rwxr-xr-xinclude/items.php8
-rw-r--r--include/nav.php20
-rw-r--r--include/notifier.php2
-rw-r--r--include/photos.php40
-rwxr-xr-xinclude/plugin.php42
-rw-r--r--include/zot.php11
-rw-r--r--install/schema_mysql.sql4
-rw-r--r--install/schema_postgres.sql2
-rw-r--r--install/update.php15
-rw-r--r--mod/_well_known.php64
-rw-r--r--mod/achievements.php87
-rw-r--r--mod/acl.php308
-rw-r--r--mod/admin.php1776
-rw-r--r--mod/api.php115
-rw-r--r--mod/appman.php102
-rw-r--r--mod/apps.php40
-rw-r--r--mod/attach.php55
-rw-r--r--mod/authtest.php54
-rw-r--r--mod/block.php86
-rw-r--r--mod/blocks.php166
-rw-r--r--mod/bookmarks.php99
-rw-r--r--mod/branchtopic.php41
-rwxr-xr-xmod/cal.php351
-rw-r--r--mod/chanview.php104
-rw-r--r--mod/chat.php255
-rw-r--r--mod/chatsvc.php162
-rw-r--r--mod/cloud.php104
-rw-r--r--mod/common.php67
-rw-r--r--mod/connect.php125
-rw-r--r--mod/connections.php318
-rw-r--r--mod/connedit.php756
-rw-r--r--mod/contactgroup.php49
-rw-r--r--mod/cover_photo.php417
-rw-r--r--mod/dav.php142
-rw-r--r--mod/directory.php419
-rw-r--r--mod/dirsearch.php456
-rw-r--r--mod/display.php340
-rw-r--r--mod/dreport.php139
-rw-r--r--mod/editblock.php192
-rw-r--r--mod/editlayout.php189
-rw-r--r--mod/editpost.php175
-rw-r--r--mod/editwebpage.php233
-rwxr-xr-xmod/events.php708
-rw-r--r--mod/fbrowser.php123
-rw-r--r--mod/feed.php42
-rw-r--r--mod/ffsapi.php65
-rw-r--r--mod/fhublocs.php80
-rw-r--r--mod/filer.php55
-rw-r--r--mod/filerm.php33
-rw-r--r--mod/filestorage.php167
-rw-r--r--mod/follow.php60
-rw-r--r--mod/fsuggest.php112
-rw-r--r--mod/getfile.php97
-rw-r--r--mod/group.php238
-rw-r--r--mod/hcard.php54
-rw-r--r--mod/help.php281
-rw-r--r--mod/home.php83
-rw-r--r--mod/hostxrd.php18
-rw-r--r--mod/id.php310
-rw-r--r--mod/impel.php201
-rw-r--r--mod/import.php547
-rw-r--r--mod/import_items.php123
-rw-r--r--mod/invite.php146
-rw-r--r--mod/item.php1262
-rw-r--r--mod/lang.php6
-rw-r--r--mod/layouts.php193
-rwxr-xr-xmod/like.php541
-rw-r--r--mod/linkinfo.php371
-rw-r--r--mod/lockview.php115
-rw-r--r--mod/locs.php126
-rw-r--r--mod/login.php7
-rw-r--r--mod/lostpass.php132
-rw-r--r--mod/magic.php167
-rw-r--r--mod/mail.php391
-rw-r--r--mod/manage.php175
-rw-r--r--mod/match.php78
-rw-r--r--mod/menu.php167
-rw-r--r--mod/message.php104
-rw-r--r--mod/mitem.php239
-rwxr-xr-xmod/mood.php140
-rw-r--r--mod/msearch.php42
-rw-r--r--mod/network.php525
-rw-r--r--mod/new_channel.php145
-rw-r--r--mod/nojs.php10
-rw-r--r--mod/notes.php34
-rw-r--r--mod/notifications.php105
-rw-r--r--mod/notify.php64
-rw-r--r--mod/oembed.php30
-rw-r--r--mod/oep.php398
-rw-r--r--mod/oexchange.php71
-rw-r--r--mod/online.php11
-rw-r--r--mod/openid.php192
-rw-r--r--mod/opensearch.php18
-rw-r--r--mod/page.php144
-rwxr-xr-xmod/pconfig.php113
-rw-r--r--mod/pdledit.php66
-rw-r--r--mod/photo.php244
-rw-r--r--mod/photos.php1378
-rw-r--r--mod/ping.php491
-rw-r--r--mod/poco.php7
-rwxr-xr-xmod/poke.php189
-rw-r--r--mod/post.php30
-rw-r--r--mod/prate.php99
-rw-r--r--mod/pretheme.php22
-rw-r--r--mod/probe.php41
-rw-r--r--mod/profile.php84
-rw-r--r--mod/profile_photo.php467
-rw-r--r--mod/profiles.php789
-rw-r--r--mod/profperm.php165
-rw-r--r--mod/public.php163
-rw-r--r--mod/pubsites.php53
-rw-r--r--mod/randprof.php12
-rw-r--r--mod/rate.php173
-rw-r--r--mod/ratings.php110
-rw-r--r--mod/ratingsearch.php70
-rw-r--r--mod/rbmark.php115
-rw-r--r--mod/regdir.php104
-rw-r--r--mod/register.php264
-rw-r--r--mod/regmod.php34
-rw-r--r--mod/regver.php22
-rw-r--r--mod/removeaccount.php66
-rw-r--r--mod/removeme.php66
-rw-r--r--mod/rmagic.php90
-rw-r--r--mod/rpost.php138
-rw-r--r--mod/rsd_xml.php24
-rw-r--r--mod/search.php222
-rw-r--r--mod/search_ac.php76
-rw-r--r--mod/service_limits.php23
-rw-r--r--mod/settings.php1144
-rwxr-xr-xmod/setup.php744
-rw-r--r--mod/share.php87
-rw-r--r--mod/sharedwithme.php107
-rw-r--r--mod/siteinfo.php88
-rw-r--r--mod/siteinfo_json.php8
-rw-r--r--mod/sitelist.php62
-rw-r--r--mod/smilies.php15
-rw-r--r--mod/sources.php168
-rw-r--r--mod/sslify.php24
-rw-r--r--mod/starred.php33
-rwxr-xr-xmod/subthread.php163
-rw-r--r--mod/suggest.php66
-rw-r--r--mod/tagger.php134
-rw-r--r--mod/tagrm.php141
-rw-r--r--mod/tasks.php107
-rw-r--r--mod/thing.php362
-rw-r--r--mod/toggle_mobile.php17
-rw-r--r--mod/toggle_safesearch.php25
-rw-r--r--mod/uexport.php65
-rw-r--r--mod/update_display.php42
-rw-r--r--mod/update_home.php38
-rw-r--r--mod/update_network.php40
-rw-r--r--mod/update_public.php37
-rw-r--r--mod/update_search.php66
-rw-r--r--mod/view.php15
-rw-r--r--mod/viewconnections.php111
-rw-r--r--mod/viewsrc.php47
-rw-r--r--mod/wall_attach.php49
-rw-r--r--mod/wall_upload.php51
-rw-r--r--mod/webfinger.php48
-rw-r--r--mod/webpages.php201
-rw-r--r--mod/wfinger.php134
-rw-r--r--mod/xchan.php41
-rw-r--r--mod/xpoco.php7
-rw-r--r--mod/xrd.php75
-rw-r--r--mod/xref.php20
-rw-r--r--mod/zfinger.php12
-rw-r--r--mod/zotfeed.php46
-rw-r--r--mod/zping.php28
-rwxr-xr-xutil/importdoc2
-rw-r--r--util/typo.php12
-rw-r--r--view/js/main.js10
-rw-r--r--view/theme/redbasic/css/style.css59
-rw-r--r--view/theme/redbasic/js/redbasic.js12
-rw-r--r--view/theme/redbasic/schema/bluegrid.css15
-rw-r--r--view/theme/redbasic/schema/dark.css11
-rw-r--r--view/theme/redbasic/schema/simple_black_on_white.css10
-rw-r--r--view/theme/redbasic/schema/simple_green_on_black.css10
-rw-r--r--view/theme/redbasic/schema/simple_white_on_black.css10
-rwxr-xr-xview/tpl/admin_site.tpl1
-rwxr-xr-xview/tpl/head.tpl1
-rwxr-xr-xview/tpl/nav.tpl365
-rw-r--r--view/tpl/nav_header.tpl49
-rw-r--r--view/tpl/rsd.tpl15
365 files changed, 29953 insertions, 28706 deletions
diff --git a/Zotlabs/Extend/Hook.php b/Zotlabs/Extend/Hook.php
new file mode 100644
index 000000000..836b29db8
--- /dev/null
+++ b/Zotlabs/Extend/Hook.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Zotlabs\Extend;
+
+
+class Hook {
+
+ static public function register($hook,$file,$function,$version = 1,$priority = 0) {
+ $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;
+
+ $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) {
+ $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;
+ }
+
+
+ /**
+ * @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(App::$hooks))
+ App::$hooks = array();
+
+ if(! array_key_exists($hook, App::$hooks))
+ App::$hooks[$hook] = array();
+
+ App::$hooks[$hook][] = array('', $fn, $priority, $version);
+ }
+
+} \ No newline at end of file
diff --git a/Zotlabs/Module/Achievements.php b/Zotlabs/Module/Achievements.php
new file mode 100644
index 000000000..8ddefb3e5
--- /dev/null
+++ b/Zotlabs/Module/Achievements.php
@@ -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
+ ));
+
+ }
+
+}
diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php
new file mode 100644
index 000000000..5c14ab599
--- /dev/null
+++ b/Zotlabs/Module/Acl.php
@@ -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();
+ }
+
+}
diff --git a/Zotlabs/Module/Admin.php b/Zotlabs/Module/Admin.php
new file mode 100644
index 000000000..1ff9065cd
--- /dev/null
+++ b/Zotlabs/Module/Admin.php
@@ -0,0 +1,1786 @@
+<?php
+namespace Zotlabs\Module;
+/**
+ * @file mod/admin.php
+ * @brief Hubzilla's admin controller.
+ *
+ * Controller for the /admin/ area.
+ */
+
+require_once('include/queue_fn.php');
+require_once('include/account.php');
+
+/**
+ * @param App &$a
+ */
+
+class Admin extends \Zotlabs\Web\Controller {
+
+ function post(){
+ logger('admin_post', LOGGER_DEBUG);
+
+ if(! is_site_admin()) {
+ return;
+ }
+
+ // urls
+ if (argc() > 1) {
+ switch (argv(1)) {
+ case 'site':
+ $this->admin_page_site_post($a);
+ break;
+ case 'users':
+ $this->admin_page_users_post($a);
+ break;
+ case 'channels':
+ $this->admin_page_channels_post($a);
+ break;
+ case 'plugins':
+ if (argc() > 2 &&
+ is_file("addon/" . argv(2) . "/" . argv(2) . ".php")){
+ @include_once("addon/" . argv(2) . "/" . argv(2) . ".php");
+ if(function_exists(argv(2).'_plugin_admin_post')) {
+ $func = argv(2) . '_plugin_admin_post';
+ $func($a);
+ }
+ }
+ goaway(z_root() . '/admin/plugins/' . argv(2) );
+ break;
+ case 'themes':
+ $theme = argv(2);
+ if (is_file("view/theme/$theme/php/config.php")){
+ require_once("view/theme/$theme/php/config.php");
+ // fixme add parent theme if derived
+ if (function_exists("theme_admin_post")){
+ theme_admin_post($a);
+ }
+ }
+ info(t('Theme settings updated.'));
+ if(is_ajax()) return;
+
+ goaway(z_root() . '/admin/themes/' . $theme );
+ break;
+ case 'logs':
+ $this->admin_page_logs_post($a);
+ break;
+ case 'hubloc':
+ $this->admin_page_hubloc_post($a);
+ break;
+ case 'security':
+ $this->admin_page_security_post($a);
+ break;
+ case 'features':
+ $this->admin_page_features_post($a);
+ break;
+ case 'dbsync':
+ $this->admin_page_dbsync_post($a);
+ break;
+ case 'profs':
+ $this->admin_page_profs_post($a);
+ break;
+ }
+ }
+
+ goaway(z_root() . '/admin' );
+ }
+
+ /**
+ * @param App &$a
+ * @return string
+ */
+ function get() {
+
+ logger('admin_content', LOGGER_DEBUG);
+
+ if(! is_site_admin()) {
+ return login(false);
+ }
+
+
+ /*
+ * Page content
+ */
+ $o = '';
+
+ // urls
+ if (argc() > 1){
+ switch (argv(1)) {
+ case 'site':
+ $o = $this->admin_page_site($a);
+ break;
+ case 'users':
+ $o = $this->admin_page_users($a);
+ break;
+ case 'channels':
+ $o = $this->admin_page_channels($a);
+ break;
+ case 'plugins':
+ $o = $this->admin_page_plugins($a);
+ break;
+ case 'themes':
+ $o = $this->admin_page_themes($a);
+ break;
+ // case 'hubloc':
+ // $o = $this->admin_page_hubloc($a);
+ // break;
+ case 'security':
+ $o = $this->admin_page_security($a);
+ break;
+ case 'features':
+ $o = $this->admin_page_features($a);
+ break;
+ case 'logs':
+ $o = $this->admin_page_logs($a);
+ break;
+ case 'dbsync':
+ $o = $this->admin_page_dbsync($a);
+ break;
+ case 'profs':
+ $o = $this->admin_page_profs($a);
+ break;
+ case 'queue':
+ $o = $this->admin_page_queue($a);
+ break;
+ default:
+ notice( t('Item not found.') );
+ }
+ } else {
+ $o = $this->admin_page_summary($a);
+ }
+
+ if(is_ajax()) {
+ echo $o;
+ killme();
+ return '';
+ } else {
+ return $o;
+ }
+ }
+
+
+ /**
+ * @brief Returns content for Admin Summary Page.
+ *
+ * @param App &$a
+ * @return string HTML from parsed admin_summary.tpl
+ */
+ function admin_page_summary(&$a) {
+
+ // list total user accounts, expirations etc.
+ $accounts = array();
+ $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires != '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account",
+ db_utcnow(),
+ db_utcnow(),
+ dbesc(NULL_DATE),
+ intval(ACCOUNT_BLOCKED)
+ );
+ if ($r) {
+ $accounts['total'] = array('label' => t('# Accounts'), 'val' => $r[0]['total']);
+ $accounts['blocked'] = array('label' => t('# blocked accounts'), 'val' => $r[0]['blocked']);
+ $accounts['expired'] = array('label' => t('# expired accounts'), 'val' => $r[0]['expired']);
+ $accounts['expiring'] = array('label' => t('# expiring accounts'), 'val' => $r[0]['expiring']);
+ }
+
+ // pending registrations
+ $r = q("SELECT COUNT(id) AS `count` FROM `register` WHERE `uid` != '0'");
+ $pending = $r[0]['count'];
+
+ // available channels, primary and clones
+ $channels = array();
+ $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0");
+ if ($r) {
+ $channels['total'] = array('label' => t('# Channels'), 'val' => $r[0]['total']);
+ $channels['main'] = array('label' => t('# primary'), 'val' => $r[0]['main']);
+ $channels['clones'] = array('label' => t('# clones'), 'val' => $r[0]['clones']);
+ }
+
+ // We can do better, but this is a quick queue status
+ $r = q("SELECT COUNT(outq_delivered) AS total FROM outq WHERE outq_delivered = 0");
+ $queue = (($r) ? $r[0]['total'] : 0);
+ $queues = array( 'label' => t('Message queues'), 'queue' => $queue );
+
+ // If no plugins active return 0, otherwise list of plugin names
+ $plugins = (count(\App::$plugins) == 0) ? count(\App::$plugins) : \App::$plugins;
+
+ // Could be extended to provide also other alerts to the admin
+ $alertmsg = '';
+ // annoy admin about upcoming unsupported PHP version
+ if (version_compare(PHP_VERSION, '5.4', '<')) {
+ $alertmsg = 'Your PHP version ' . PHP_VERSION . ' will not be supported with the next major release of $Projectname. You are strongly urged to upgrade to a current version.'
+ . '<br>PHP 5.3 has reached its <a href="http://php.net/eol.php" class="alert-link">End of Life (EOL)</a> in August 2014.'
+ . ' A list about current PHP versions can be found <a href="http://php.net/supported-versions.php" class="alert-link">here</a>.';
+ }
+
+ $t = get_markup_template('admin_summary.tpl');
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Summary'),
+ '$adminalertmsg' => $alertmsg,
+ '$queues' => $queues,
+ '$accounts' => array( t('Registered accounts'), $accounts),
+ '$pending' => array( t('Pending registrations'), $pending),
+ '$channels' => array( t('Registered channels'), $channels),
+ '$plugins' => array( t('Active plugins'), $plugins ),
+ '$version' => array( t('Version'), RED_VERSION),
+ '$build' => get_config('system', 'db_version')
+ ));
+ }
+
+
+ /**
+ * @brief POST handler for Admin Site Page.
+ *
+ * @param App &$a
+ */
+ function admin_page_site_post(&$a){
+ if (!x($_POST, 'page_site')){
+ return;
+ }
+
+ check_form_security_token_redirectOnErr('/admin/site', 'admin_site');
+
+ $sitename = ((x($_POST,'sitename')) ? notags(trim($_POST['sitename'])) : '');
+ $banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false);
+ $admininfo = ((x($_POST,'admininfo')) ? trim($_POST['admininfo']) : false);
+ $language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : '');
+ $theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : '');
+ $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : '');
+ // $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : '');
+ $maximagesize = ((x($_POST,'maximagesize')) ? intval(trim($_POST['maximagesize'])) : 0);
+
+ $register_policy = ((x($_POST,'register_policy')) ? intval(trim($_POST['register_policy'])) : 0);
+
+ $access_policy = ((x($_POST,'access_policy')) ? intval(trim($_POST['access_policy'])) : 0);
+ $invite_only = ((x($_POST,'invite_only')) ? True : False);
+ $abandon_days = ((x($_POST,'abandon_days')) ? intval(trim($_POST['abandon_days'])) : 0);
+
+ $register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : '');
+ $frontpage = ((x($_POST,'frontpage')) ? notags(trim($_POST['frontpage'])) : '');
+ $mirror_frontpage = ((x($_POST,'mirror_frontpage')) ? intval(trim($_POST['mirror_frontpage'])) : 0);
+ $directory_server = ((x($_POST,'directory_server')) ? trim($_POST['directory_server']) : '');
+ $allowed_sites = ((x($_POST,'allowed_sites')) ? notags(trim($_POST['allowed_sites'])) : '');
+ $allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : '');
+ $not_allowed_email = ((x($_POST,'not_allowed_email')) ? notags(trim($_POST['not_allowed_email'])) : '');
+ $force_publish = ((x($_POST,'publish_all')) ? True : False);
+ $disable_discover_tab = ((x($_POST,'disable_discover_tab')) ? False : True);
+ $login_on_homepage = ((x($_POST,'login_on_homepage')) ? True : False);
+ $enable_context_help = ((x($_POST,'enable_context_help')) ? True : False);
+ $global_directory = ((x($_POST,'directory_submit_url')) ? notags(trim($_POST['directory_submit_url'])) : '');
+ $no_community_page = !((x($_POST,'no_community_page')) ? True : False);
+ $default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0);
+
+ $verifyssl = ((x($_POST,'verifyssl')) ? True : False);
+ $proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
+ $proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
+ $timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60);
+ $delivery_interval = ((x($_POST,'delivery_interval'))? intval(trim($_POST['delivery_interval'])) : 0);
+ $delivery_batch_count = ((x($_POST,'delivery_batch_count') && $_POST['delivery_batch_count'] > 0)? intval(trim($_POST['delivery_batch_count'])) : 1);
+ $poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0);
+ $maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
+ $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
+ $verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
+
+ set_config('system', 'feed_contacts', $feed_contacts);
+ set_config('system', 'delivery_interval', $delivery_interval);
+ set_config('system', 'delivery_batch_count', $delivery_batch_count);
+ set_config('system', 'poll_interval', $poll_interval);
+ set_config('system', 'maxloadavg', $maxloadavg);
+ set_config('system', 'frontpage', $frontpage);
+ set_config('system', 'mirror_frontpage', $mirror_frontpage);
+ set_config('system', 'sitename', $sitename);
+ set_config('system', 'login_on_homepage', $login_on_homepage);
+ set_config('system', 'enable_context_help', $enable_context_help);
+ set_config('system', 'verify_email', $verify_email);
+ set_config('system', 'default_expire_days', $default_expire_days);
+
+ if($directory_server)
+ set_config('system','directory_server',$directory_server);
+
+ if ($banner == '') {
+ del_config('system', 'banner');
+ } else {
+ set_config('system', 'banner', $banner);
+ }
+
+ if ($admininfo == ''){
+ del_config('system', 'admininfo');
+ } else {
+ require_once('include/text.php');
+ linkify_tags($a, $admininfo, local_channel());
+ set_config('system', 'admininfo', $admininfo);
+ }
+ set_config('system', 'language', $language);
+ set_config('system', 'theme', $theme);
+ if ( $theme_mobile === '---' ) {
+ del_config('system', 'mobile_theme');
+ } else {
+ set_config('system', 'mobile_theme', $theme_mobile);
+ }
+ // set_config('system','site_channel', $site_channel);
+ set_config('system','maximagesize', $maximagesize);
+
+ set_config('system','register_policy', $register_policy);
+ set_config('system','invitation_only', $invite_only);
+ set_config('system','access_policy', $access_policy);
+ set_config('system','account_abandon_days', $abandon_days);
+ set_config('system','register_text', $register_text);
+ set_config('system','allowed_sites', $allowed_sites);
+ set_config('system','allowed_email', $allowed_email);
+ set_config('system','not_allowed_email', $not_allowed_email);
+ set_config('system','publish_all', $force_publish);
+ set_config('system','disable_discover_tab', $disable_discover_tab);
+ if ($global_directory == '') {
+ del_config('system', 'directory_submit_url');
+ } else {
+ set_config('system', 'directory_submit_url', $global_directory);
+ }
+
+ set_config('system','no_community_page', $no_community_page);
+ set_config('system','no_utf', $no_utf);
+ set_config('system','verifyssl', $verifyssl);
+ set_config('system','proxyuser', $proxyuser);
+ set_config('system','proxy', $proxy);
+ set_config('system','curl_timeout', $timeout);
+
+ info( t('Site settings updated.') . EOL);
+ goaway(z_root() . '/admin/site' );
+ }
+
+ /**
+ * @brief Admin page site.
+ *
+ * @param App $a
+ * @return string
+ */
+ function admin_page_site(&$a) {
+
+ /* Installed langs */
+ $lang_choices = array();
+ $langs = glob('view/*/hstrings.php');
+
+ if(is_array($langs) && count($langs)) {
+ if(! in_array('view/en/hstrings.php',$langs))
+ $langs[] = 'view/en/';
+ asort($langs);
+ foreach($langs as $l) {
+ $t = explode("/",$l);
+ $lang_choices[$t[1]] = $t[1];
+ }
+ }
+
+ /* Installed themes */
+ $theme_choices_mobile["---"] = t("Default");
+ $theme_choices = array();
+ $files = glob('view/theme/*');
+ if($files) {
+ foreach($files as $file) {
+ $vars = '';
+ $f = basename($file);
+ if (file_exists($file . '/library'))
+ continue;
+ if (file_exists($file . '/mobile'))
+ $vars = t('mobile');
+ if (file_exists($file . '/experimental'))
+ $vars .= t('experimental');
+ if (file_exists($file . '/unsupported'))
+ $vars .= t('unsupported');
+ if ($vars) {
+ $theme_choices[$f] = $f . ' (' . $vars . ')';
+ $theme_choices_mobile[$f] = $f . ' (' . $vars . ')';
+ }
+ else {
+ $theme_choices[$f] = $f;
+ $theme_choices_mobile[$f] = $f;
+ }
+ }
+ }
+
+ $dir_choices = null;
+ $dirmode = get_config('system','directory_mode');
+ $realm = get_directory_realm();
+
+ // directory server should not be set or settable unless we are a directory client
+
+ if($dirmode == DIRECTORY_MODE_NORMAL) {
+ $x = q("select site_url from site where site_flags in (%d,%d) and site_realm = '%s'",
+ intval(DIRECTORY_MODE_SECONDARY),
+ intval(DIRECTORY_MODE_PRIMARY),
+ dbesc($realm)
+ );
+ if($x) {
+ $dir_choices = array();
+ foreach($x as $xx) {
+ $dir_choices[$xx['site_url']] = $xx['site_url'];
+ }
+ }
+ }
+
+ /* Banner */
+
+ $banner = get_config('system', 'banner');
+ if($banner === false)
+ $banner = get_config('system','sitename');
+
+ $banner = htmlspecialchars($banner);
+
+ /* Admin Info */
+ $admininfo = get_config('system', 'admininfo');
+
+ /* Register policy */
+ $register_choices = Array(
+ REGISTER_CLOSED => t("No"),
+ REGISTER_APPROVE => t("Yes - with approval"),
+ REGISTER_OPEN => t("Yes")
+ );
+
+ /* Acess policy */
+ $access_choices = Array(
+ ACCESS_PRIVATE => t("My site is not a public server"),
+ ACCESS_PAID => t("My site has paid access only"),
+ ACCESS_FREE => t("My site has free access only"),
+ ACCESS_TIERED => t("My site offers free accounts with optional paid upgrades")
+ );
+
+ // $ssl_choices = array(
+ // SSL_POLICY_NONE => t("No SSL policy, links will track page SSL state"),
+ // SSL_POLICY_FULL => t("Force all links to use SSL")
+ // );
+
+ $discover_tab = get_config('system','disable_discover_tab');
+ // $disable public streams by default
+ if($discover_tab === false)
+ $discover_tab = 1;
+ // now invert the logic for the setting.
+ $discover_tab = (1 - $discover_tab);
+
+
+ $homelogin = get_config('system','login_on_homepage');
+ $enable_context_help = get_config('system','enable_context_help');
+
+ $t = get_markup_template("admin_site.tpl");
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Site'),
+ '$submit' => t('Submit'),
+ '$registration' => t('Registration'),
+ '$upload' => t('File upload'),
+ '$corporate' => t('Policies'),
+ '$advanced' => t('Advanced'),
+
+ '$baseurl' => z_root(),
+ // name, label, value, help string, extra data...
+ '$sitename' => array('sitename', t("Site name"), htmlspecialchars(get_config('system','sitename'), ENT_QUOTES, 'UTF-8'),''),
+ '$banner' => array('banner', t("Banner/Logo"), $banner, ""),
+ '$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")),
+ '$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
+ '$theme' => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices),
+ '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile),
+ // '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")),
+ '$feed_contacts' => array('feed_contacts', t('Allow Feeds as Connections'),get_config('system','feed_contacts'),t('(Heavy system resource usage)')),
+ '$maximagesize' => array('maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.")),
+ '$register_policy' => array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices),
+ '$invite_only' => array('invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. Above register policy must be set to Yes.")),
+ '$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), "This is displayed on the public server site list.", $access_choices),
+ '$register_text' => array('register_text', t("Register text"), htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")),
+ '$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'public' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")),
+ '$mirror_frontpage' => array('mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting')),
+ '$abandon_days' => array('abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')),
+ '$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")),
+ '$allowed_email' => array('allowed_email', t("Allowed email domains"), get_config('system','allowed_email'), t("Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains")),
+ '$not_allowed_email' => array('not_allowed_email', t("Not allowed email domains"), get_config('system','not_allowed_email'), t("Comma separated list of domains which are not allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains, unless allowed domains have been defined.")),
+ '$verify_email' => array('verify_email', t("Verify Email Addresses"), get_config('system','verify_email'), t("Check to verify email addresses used in account registration (recommended).")),
+ '$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")),
+ '$disable_discover_tab' => array('disable_discover_tab', t('Import Public Streams'), $discover_tab, t('Import and allow access to public content pulled from other sites. Warning: this content is unmoderated.')),
+ '$login_on_homepage' => array('login_on_homepage', t("Login on Homepage"),((intval($homelogin) || $homelogin === false) ? 1 : '') , t("Present a login box to visitors on the home page if no other content has been configured.")),
+ '$enable_context_help' => array('enable_context_help', t("Enable context help"),((intval($enable_context_help) === 1 || $enable_context_help === false) ? 1 : 0) , t("Display contextual help for the current page when the help button is pressed.")),
+
+ '$directory_server' => (($dir_choices) ? array('directory_server', t("Directory Server URL"), get_config('system','directory_server'), t("Default directory server"), $dir_choices) : null),
+
+ '$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
+ '$proxy' => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
+ '$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
+ '$delivery_interval' => array('delivery_interval', t("Delivery interval"), (x(get_config('system','delivery_interval'))?get_config('system','delivery_interval'):2), t("Delay background delivery processes by this many seconds to reduce system load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 for large dedicated servers.")),
+ '$delivery_batch_count' => array('delivery_batch_count', t('Deliveries per process'),(x(get_config('system','delivery_batch_count'))?get_config('system','delivery_batch_count'):1), t("Number of deliveries to attempt in a single operating system process. Adjust if necessary to tune system performance. Recommend: 1-5.")),
+ '$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
+ '$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
+ '$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
+ '$form_security_token' => get_form_security_token("admin_site"),
+ ));
+ }
+
+ function admin_page_hubloc_post(&$a){
+ check_form_security_token_redirectOnErr('/admin/hubloc', 'admin_hubloc');
+ require_once('include/zot.php');
+
+ //prepare for ping
+
+ if ( $_POST['hublocid']) {
+ $hublocid = $_POST['hublocid'];
+ $arrhublocurl = q("SELECT hubloc_url FROM hubloc WHERE hubloc_id = %d ",
+ intval($hublocid)
+ );
+ $hublocurl = $arrhublocurl[0]['hubloc_url'] . '/post';
+
+ //perform ping
+ $m = zot_build_packet(\App::get_channel(),'ping');
+ $r = zot_zot($hublocurl,$m);
+ //handle results and set the hubloc flags in db to make results visible
+ $r2 = $r['body'];
+ $r3 = $r2['success'];
+ if ( $r3['success'] == True ){
+ //set HUBLOC_OFFLINE to 0
+ logger(' success = true ',LOGGER_DEBUG);
+ } else {
+ //set HUBLOC_OFFLINE to 1
+ logger(' success = false ', LOGGER_DEBUG);
+ }
+
+ //unfotunatly zping wont work, I guess return format is not correct
+ //require_once('mod/zping.php');
+ //$r = zping_content($hublocurl);
+ //logger('zping answer: ' . $r, LOGGER_DEBUG);
+
+ //in case of repair store new pub key for tested hubloc (all channel with this hubloc) in db
+ //after repair set hubloc flags to 0
+ }
+
+ goaway(z_root() . '/admin/hubloc' );
+ }
+
+ function trim_array_elems($arr) {
+ $narr = array();
+
+ if($arr && is_array($arr)) {
+ for($x = 0; $x < count($arr); $x ++) {
+ $y = trim($arr[$x]);
+ if($y)
+ $narr[] = $y;
+ }
+ }
+ return $narr;
+ }
+
+ function admin_page_security_post(&$a){
+ check_form_security_token_redirectOnErr('/admin/security', 'admin_security');
+
+ logger('post: ' . print_r($_POST,true));
+
+ $block_public = ((x($_POST,'block_public')) ? True : False);
+ set_config('system','block_public',$block_public);
+
+ $ws = trim_array_elems(explode("\n",$_POST['whitelisted_sites']));
+ set_config('system','whitelisted_sites',$ws);
+
+ $bs = trim_array_elems(explode("\n",$_POST['blacklisted_sites']));
+ set_config('system','blacklisted_sites',$bs);
+
+ $wc = trim_array_elems(explode("\n",$_POST['whitelisted_channels']));
+ set_config('system','whitelisted_channels',$wc);
+
+ $bc = trim_array_elems(explode("\n",$_POST['blacklisted_channels']));
+ set_config('system','blacklisted_channels',$bc);
+
+ $embed_coop = ((x($_POST,'embed_coop')) ? True : False);
+ set_config('system','embed_coop',$embed_coop);
+
+ $we = trim_array_elems(explode("\n",$_POST['embed_allow']));
+ set_config('system','embed_allow',$we);
+
+ $be = trim_array_elems(explode("\n",$_POST['embed_deny']));
+ set_config('system','embed_deny',$be);
+
+ goaway(z_root() . '/admin/security');
+ }
+
+
+
+
+ function admin_page_features_post(&$a) {
+
+ check_form_security_token_redirectOnErr('/admin/features', 'admin_manage_features');
+
+ logger('postvars: ' . print_r($_POST,true));
+
+ $arr = array();
+ $features = get_features(false);
+
+ foreach($features as $fname => $fdata) {
+ foreach(array_slice($fdata,1) as $f) {
+ $feature = $f[0];
+
+ if(array_key_exists('feature_' . $feature,$_POST))
+ $val = intval($_POST['feature_' . $feature]);
+ else
+ $val = 0;
+ set_config('feature',$feature,$val);
+
+ if(array_key_exists('featurelock_' . $feature,$_POST))
+ set_config('feature_lock',$feature,$val);
+ else
+ del_config('feature_lock',$feature);
+ }
+ }
+
+ goaway(z_root() . '/admin/features' );
+
+ }
+
+ function admin_page_features(&$a) {
+
+ if((argc() > 1) && (argv(1) === 'features')) {
+ $arr = array();
+ $features = get_features(false);
+
+ foreach($features as $fname => $fdata) {
+ $arr[$fname] = array();
+ $arr[$fname][0] = $fdata[0];
+ foreach(array_slice($fdata,1) as $f) {
+
+ $set = get_config('feature',$f[0]);
+ if($set === false)
+ $set = $f[3];
+ $arr[$fname][1][] = array(
+ array('feature_' .$f[0],$f[1],$set,$f[2],array(t('Off'),t('On'))),
+ array('featurelock_' .$f[0],sprintf( t('Lock feature %s'),$f[1]),(($f[4] !== false) ? 1 : 0),'',array(t('Off'),t('On')))
+ );
+ }
+ }
+
+ $tpl = get_markup_template("admin_settings_features.tpl");
+ $o .= replace_macros($tpl, array(
+ '$form_security_token' => get_form_security_token("admin_manage_features"),
+ '$title' => t('Manage Additional Features'),
+ '$features' => $arr,
+ '$submit' => t('Submit'),
+ ));
+
+ return $o;
+ }
+ }
+
+
+
+
+
+ function admin_page_hubloc(&$a) {
+ $hubloc = q("SELECT hubloc_id, hubloc_addr, hubloc_host, hubloc_status FROM hubloc");
+
+ if(! $hubloc){
+ notice( t('No server found') . EOL);
+ goaway(z_root() . '/admin/hubloc');
+ }
+
+ $t = get_markup_template('admin_hubloc.tpl');
+ return replace_macros($t, array(
+ '$hubloc' => $hubloc,
+ '$th_hubloc' => array(t('ID'), t('for channel'), t('on server'), t('Status')),
+ '$title' => t('Administration'),
+ '$page' => t('Server'),
+ '$queues' => $queues,
+ //'$accounts' => $accounts, /*$accounts is empty here*/
+ '$pending' => array( t('Pending registrations'), $pending),
+ '$plugins' => array( t('Active plugins'), \App::$plugins ),
+ '$form_security_token' => get_form_security_token('admin_hubloc')
+ ));
+ }
+
+ function admin_page_security(&$a) {
+
+ $whitesites = get_config('system','whitelisted_sites');
+ $whitesites_str = ((is_array($whitesites)) ? implode($whitesites,"\n") : '');
+
+ $blacksites = get_config('system','blacklisted_sites');
+ $blacksites_str = ((is_array($blacksites)) ? implode($blacksites,"\n") : '');
+
+
+ $whitechannels = get_config('system','whitelisted_channels');
+ $whitechannels_str = ((is_array($whitechannels)) ? implode($whitechannels,"\n") : '');
+
+ $blackchannels = get_config('system','blacklisted_channels');
+ $blackchannels_str = ((is_array($blackchannels)) ? implode($blackchannels,"\n") : '');
+
+
+ $whiteembeds = get_config('system','embed_allow');
+ $whiteembeds_str = ((is_array($whiteembeds)) ? implode($whiteembeds,"\n") : '');
+
+ $blackembeds = get_config('system','embed_deny');
+ $blackembeds_str = ((is_array($blackembeds)) ? implode($blackembeds,"\n") : '');
+
+ $embed_coop = intval(get_config('system','embed_coop'));
+
+ // wait to implement this until we have a co-op in place.
+ // if((! $whiteembeds) && (! $blackembeds) && (! $embed_coop))
+ // $whiteembeds_str = "youtube.com\nyoutu.be\ntwitter.com\nvimeo.com\nsoundcloud.com\nwikipedia.com";
+
+ $t = get_markup_template('admin_security.tpl');
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Security'),
+ '$form_security_token' => get_form_security_token('admin_security'),
+ '$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently authenticated.")),
+ '$whitelisted_sites' => array('whitelisted_sites', t('Allow communications only from these sites'), $whitesites_str, t('One site per line. Leave empty to allow communication from anywhere by default')),
+ '$blacklisted_sites' => array('blacklisted_sites', t('Block communications from these sites'), $blacksites_str, ''),
+ '$whitelisted_channels' => array('whitelisted_channels', t('Allow communications only from these channels'), $whitechannels_str, t('One channel (hash) per line. Leave empty to allow from any channel by default')),
+ '$blacklisted_channels' => array('blacklisted_channels', t('Block communications from these channels'), $blackchannels_str, ''),
+ '$embed_allow' => array('embed_allow', t('Allow embedded HTML content only from these domains'), $whiteembeds_str, t('One site per line. Leave empty to allow from any site by default')),
+ '$embed_deny' => array('embed_deny', t('Block embedded HTML from these domains'), $blackembeds_str, ''),
+
+ '$embed_coop' => array('embed_coop', t('Cooperative embed security'), $embed_coop, t('Enable to share embed security with other compatible sites/hubs')),
+ '$submit' => t('Submit')
+ ));
+ }
+
+
+
+
+ function admin_page_dbsync(&$a) {
+ $o = '';
+
+ if(argc() > 3 && intval(argv(3)) && argv(2) === 'mark') {
+ set_config('database', 'update_r' . intval(argv(3)), 'success');
+ if(intval(get_config('system','db_version')) <= intval(argv(3)))
+ set_config('system','db_version',intval(argv(3)) + 1);
+ info( t('Update has been marked successful') . EOL);
+ goaway(z_root() . '/admin/dbsync');
+ }
+
+ if(argc() > 2 && intval(argv(2))) {
+ require_once('install/update.php');
+ $func = 'update_r' . intval(argv(2));
+ if(function_exists($func)) {
+ $retval = $func();
+ if($retval === UPDATE_FAILED) {
+ $o .= sprintf( t('Executing %s failed. Check system logs.'), $func);
+ }
+ elseif($retval === UPDATE_SUCCESS) {
+ $o .= sprintf( t('Update %s was successfully applied.'), $func);
+ set_config('database',$func, 'success');
+ }
+ else
+ $o .= sprintf( t('Update %s did not return a status. Unknown if it succeeded.'), $func);
+ }
+ else
+ $o .= sprintf( t('Update function %s could not be found.'), $func);
+
+ return $o;
+ }
+
+ $failed = array();
+ $r = q("select * from config where `cat` = 'database' ");
+ if(count($r)) {
+ foreach($r as $rr) {
+ $upd = intval(substr($rr['k'],8));
+ if($rr['v'] === 'success')
+ continue;
+ $failed[] = $upd;
+ }
+ }
+ if(! count($failed))
+ return '<div class="generic-content-wrapper-styled"><h3>' . t('No failed updates.') . '</h3></div>';
+
+ $o = replace_macros(get_markup_template('failed_updates.tpl'),array(
+ '$base' => z_root(),
+ '$banner' => t('Failed Updates'),
+ '$desc' => '',
+ '$mark' => t('Mark success (if update was manually applied)'),
+ '$apply' => t('Attempt to execute this update step automatically'),
+ '$failed' => $failed
+ ));
+
+ return $o;
+ }
+
+ function admin_page_queue($a) {
+ $o = '';
+
+ $expert = ((array_key_exists('expert',$_REQUEST)) ? intval($_REQUEST['expert']) : 0);
+
+ if($_REQUEST['drophub']) {
+ require_once('hubloc.php');
+ hubloc_mark_as_down($_REQUEST['drophub']);
+ remove_queue_by_posturl($_REQUEST['drophub']);
+ }
+
+ if($_REQUEST['emptyhub']) {
+ remove_queue_by_posturl($_REQUEST['emptyhub']);
+ }
+
+ $r = q("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq
+ where outq_delivered = 0 group by outq_posturl order by total desc");
+
+ for($x = 0; $x < count($r); $x ++) {
+ $r[$x]['eurl'] = urlencode($r[$x]['outq_posturl']);
+ $r[$x]['connected'] = datetime_convert('UTC',date_default_timezone_get(),$r[$x]['connected'],'Y-m-d');
+ }
+
+ $o = replace_macros(get_markup_template('admin_queue.tpl'), array(
+ '$banner' => t('Queue Statistics'),
+ '$numentries' => t('Total Entries'),
+ '$priority' => t('Priority'),
+ '$desturl' => t('Destination URL'),
+ '$nukehub' => t('Mark hub permanently offline'),
+ '$empty' => t('Empty queue for this hub'),
+ '$lastconn' => t('Last known contact'),
+ '$hasentries' => ((count($r)) ? true : false),
+ '$entries' => $r,
+ '$expert' => $expert
+ ));
+
+ return $o;
+ }
+
+ /**
+ * @brief Handle POST actions on users admin page.
+ *
+ * This function is called when on the admin user/account page the form was
+ * submitted to handle multiple operations at once. If one of the icons next
+ * to an entry are pressed the function admin_page_users() will handle this.
+ *
+ * @param App $a
+ */
+ function admin_page_users_post($a) {
+ $pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() );
+ $users = ( x($_POST, 'user') ? $_POST['user'] : array() );
+ $blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : array() );
+
+ check_form_security_token_redirectOnErr('/admin/users', 'admin_users');
+
+ // change to switch structure?
+ // account block/unblock button was submitted
+ if (x($_POST, 'page_users_block')) {
+ for ($i = 0; $i < count($users); $i++) {
+ // if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
+ $op = ($blocked[$i]) ? '& ~' : '| ';
+ q("UPDATE account SET account_flags = (account_flags $op%d) WHERE account_id = %d",
+ intval(ACCOUNT_BLOCKED),
+ intval($users[$i])
+ );
+ }
+ notice( sprintf( tt("%s account blocked/unblocked", "%s account blocked/unblocked", count($users)), count($users)) );
+ }
+ // account delete button was submitted
+ if (x($_POST, 'page_users_delete')) {
+ require_once('include/Contact.php');
+ foreach ($users as $uid){
+ account_remove($uid, true, false);
+ }
+ notice( sprintf( tt("%s account deleted", "%s accounts deleted", count($users)), count($users)) );
+ }
+ // registration approved button was submitted
+ if (x($_POST, 'page_users_approve')) {
+ foreach ($pending as $hash) {
+ account_allow($hash);
+ }
+ }
+ // registration deny button was submitted
+ if (x($_POST, 'page_users_deny')) {
+ foreach ($pending as $hash) {
+ account_deny($hash);
+ }
+ }
+
+ goaway(z_root() . '/admin/users' );
+ }
+
+ /**
+ * @brief Generate users admin page and handle single item operations.
+ *
+ * This function generates the users/account admin page and handles the actions
+ * if an icon next to an entry was clicked. If several items were selected and
+ * the form was submitted it is handled by the function admin_page_users_post().
+ *
+ * @param App &$a
+ * @return string
+ */
+ function admin_page_users(&$a){
+ if (argc() > 2) {
+ $uid = argv(3);
+ $account = q("SELECT * FROM account WHERE account_id = %d",
+ intval($uid)
+ );
+
+ if (! $account) {
+ notice( t('Account not found') . EOL);
+ goaway(z_root() . '/admin/users' );
+ }
+
+ check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
+
+ switch (argv(2)){
+ case 'delete':
+ // delete user
+ require_once('include/Contact.php');
+ account_remove($uid,true,false);
+
+ notice( sprintf(t("Account '%s' deleted"), $account[0]['account_email']) . EOL);
+ break;
+ case 'block':
+ q("UPDATE account SET account_flags = ( account_flags | %d ) WHERE account_id = %d",
+ intval(ACCOUNT_BLOCKED),
+ intval($uid)
+ );
+
+ notice( sprintf( t("Account '%s' blocked") , $account[0]['account_email']) . EOL);
+ break;
+ case 'unblock':
+ q("UPDATE account SET account_flags = ( account_flags & ~%d ) WHERE account_id = %d",
+ intval(ACCOUNT_BLOCKED),
+ intval($uid)
+ );
+
+ notice( sprintf( t("Account '%s' unblocked"), $account[0]['account_email']) . EOL);
+ break;
+ }
+
+ goaway(z_root() . '/admin/users' );
+ }
+
+ /* get pending */
+ $pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d )>0 ",
+ intval(ACCOUNT_PENDING)
+ );
+
+ /* get users */
+
+ $total = q("SELECT count(*) as total FROM account");
+ if (count($total)) {
+ \App::set_pager_total($total[0]['total']);
+ \App::set_pager_itemspage(100);
+ }
+
+
+ // We'll still need to link email addresses to admin/users/channels or some such, but this bit doesn't exist yet.
+ // That's where we need to be doing last post/channel flags/etc, not here.
+
+ $serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : '');
+
+ $order = " order by account_email asc ";
+ if($_REQUEST['order'] === 'expires')
+ $order = " order by account_expires desc ";
+ if($_REQUEST['order'] === 'created')
+ $order = " order by account_created desc ";
+
+ $users = q("SELECT `account_id` , `account_email`, `account_lastlog`, `account_created`, `account_expires`, " . "`account_service_class`, ( account_flags & %d )>0 as `blocked`, " .
+ "(SELECT %s FROM channel as ch " .
+ "WHERE ch.channel_account_id = ac.account_id and ch.channel_removed = 0 ) as `channels` " .
+ "FROM account as ac where true $serviceclass $order limit %d offset %d ",
+ intval(ACCOUNT_BLOCKED),
+ db_concat('ch.channel_address', ' '),
+ intval(\App::$pager['itemspage']),
+ intval(\App::$pager['start'])
+ );
+
+ // function _setup_users($e){
+ // $accounts = Array(
+ // t('Normal Account'),
+ // t('Soapbox Account'),
+ // t('Community/Celebrity Account'),
+ // t('Automatic Friend Account')
+ // );
+
+ // $e['page_flags'] = $accounts[$e['page-flags']];
+ // $e['register_date'] = relative_date($e['register_date']);
+ // $e['login_date'] = relative_date($e['login_date']);
+ // $e['lastitem_date'] = relative_date($e['lastitem_date']);
+ // return $e;
+ // }
+ // $users = array_map("_setup_users", $users);
+
+ $t = get_markup_template('admin_users.tpl');
+ $o = replace_macros($t, array(
+ // strings //
+ '$title' => t('Administration'),
+ '$page' => t('Users'),
+ '$submit' => t('Submit'),
+ '$select_all' => t('select all'),
+ '$h_pending' => t('User registrations waiting for confirm'),
+ '$th_pending' => array( t('Request date'), t('Email') ),
+ '$no_pending' => t('No registrations.'),
+ '$approve' => t('Approve'),
+ '$deny' => t('Deny'),
+ '$delete' => t('Delete'),
+ '$block' => t('Block'),
+ '$unblock' => t('Unblock'),
+
+ '$h_users' => t('Users'),
+ '$th_users' => array( t('ID'), t('Email'), t('All Channels'), t('Register date'), t('Last login'), t('Expires'), t('Service Class')),
+
+ '$confirm_delete_multi' => t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?'),
+ '$confirm_delete' => t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?'),
+
+ '$form_security_token' => get_form_security_token("admin_users"),
+
+ // values //
+ '$baseurl' => z_root(),
+
+ '$pending' => $pending,
+ '$users' => $users,
+ ));
+ $o .= paginate($a);
+
+ return $o;
+ }
+
+
+ /**
+ * @brief Channels admin page.
+ *
+ * @param App &$a
+ */
+ function admin_page_channels_post(&$a) {
+ $channels = ( x($_POST, 'channel') ? $_POST['channel'] : Array() );
+
+ check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels');
+
+ $xor = db_getfunc('^');
+
+ if (x($_POST,'page_channels_block')){
+ foreach($channels as $uid){
+ q("UPDATE channel SET channel_pageflags = ( channel_pageflags $xor %d ) where channel_id = %d",
+ intval(PAGE_CENSORED),
+ intval( $uid )
+ );
+ proc_run('php','include/directory.php',$uid,'nopush');
+ }
+ notice( sprintf( tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)) );
+ }
+ if (x($_POST,'page_channels_code')){
+ foreach($channels as $uid){
+ q("UPDATE channel SET channel_pageflags = ( channel_pageflags $xor %d ) where channel_id = %d",
+ intval(PAGE_ALLOWCODE),
+ intval( $uid )
+ );
+ }
+ notice( sprintf( tt("%s channel code allowed/disallowed", "%s channels code allowed/disallowed", count($channels)), count($channels)) );
+ }
+ if (x($_POST,'page_channels_delete')){
+ require_once("include/Contact.php");
+ foreach($channels as $uid){
+ channel_remove($uid,true);
+ }
+ notice( sprintf( tt("%s channel deleted", "%s channels deleted", count($channels)), count($channels)) );
+ }
+
+ goaway(z_root() . '/admin/channels' );
+ }
+
+ /**
+ * @brief
+ *
+ * @param App &$a
+ * @return string
+ */
+ function admin_page_channels(&$a){
+ if (argc() > 2) {
+ $uid = argv(3);
+ $channel = q("SELECT * FROM channel WHERE channel_id = %d",
+ intval($uid)
+ );
+
+ if (! $channel) {
+ notice( t('Channel not found') . EOL);
+ goaway(z_root() . '/admin/channels' );
+ }
+
+ switch(argv(2)) {
+ case "delete":{
+ check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
+ // delete channel
+ require_once("include/Contact.php");
+ channel_remove($uid,true);
+
+ notice( sprintf(t("Channel '%s' deleted"), $channel[0]['channel_name']) . EOL);
+ }; break;
+
+ case "block":{
+ check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
+ $pflags = $channel[0]['channel_pageflags'] ^ PAGE_CENSORED;
+ q("UPDATE channel SET channel_pageflags = %d where channel_id = %d",
+ intval($pflags),
+ intval( $uid )
+ );
+ proc_run('php','include/directory.php',$uid,'nopush');
+
+ notice( sprintf( (($pflags & PAGE_CENSORED) ? t("Channel '%s' censored"): t("Channel '%s' uncensored")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL);
+ }; break;
+
+ case "code":{
+ check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
+ $pflags = $channel[0]['channel_pageflags'] ^ PAGE_ALLOWCODE;
+ q("UPDATE channel SET channel_pageflags = %d where channel_id = %d",
+ intval($pflags),
+ intval( $uid )
+ );
+
+ notice( sprintf( (($pflags & PAGE_ALLOWCODE) ? t("Channel '%s' code allowed"): t("Channel '%s' code disallowed")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL);
+ }; break;
+
+ default:
+ break;
+ }
+ goaway(z_root() . '/admin/channels' );
+ }
+
+ /* get channels */
+
+ $total = q("SELECT count(*) as total FROM channel where channel_removed = 0 and channel_system = 0");
+ if($total) {
+ \App::set_pager_total($total[0]['total']);
+ \App::set_pager_itemspage(100);
+ }
+
+ $order = " order by channel_name asc ";
+
+ $channels = q("SELECT * from channel where channel_removed = 0 and channel_system = 0 $order limit %d offset %d ",
+ intval(\App::$pager['itemspage']),
+ intval(\App::$pager['start'])
+ );
+
+ if($channels) {
+ for($x = 0; $x < count($channels); $x ++) {
+ if($channels[$x]['channel_pageflags'] & PAGE_CENSORED)
+ $channels[$x]['blocked'] = true;
+ else
+ $channels[$x]['blocked'] = false;
+
+ if($channels[$x]['channel_pageflags'] & PAGE_ALLOWCODE)
+ $channels[$x]['allowcode'] = true;
+ else
+ $channels[$x]['allowcode'] = false;
+ }
+ }
+
+ $t = get_markup_template("admin_channels.tpl");
+ $o = replace_macros($t, array(
+ // strings //
+ '$title' => t('Administration'),
+ '$page' => t('Channels'),
+ '$submit' => t('Submit'),
+ '$select_all' => t('select all'),
+ '$delete' => t('Delete'),
+ '$block' => t('Censor'),
+ '$unblock' => t('Uncensor'),
+ '$code' => t('Allow Code'),
+ '$uncode' => t('Disallow Code'),
+ '$h_channels' => t('Channel'),
+ '$th_channels' => array( t('UID'), t('Name'), t('Address')),
+
+ '$confirm_delete_multi' => t('Selected channels will be deleted!\n\nEverything that was posted in these channels on this site will be permanently deleted!\n\nAre you sure?'),
+ '$confirm_delete' => t('The channel {0} will be deleted!\n\nEverything that was posted in this channel on this site will be permanently deleted!\n\nAre you sure?'),
+
+ '$form_security_token' => get_form_security_token("admin_channels"),
+
+ // values //
+ '$baseurl' => z_root(),
+ '$channels' => $channels,
+ ));
+ $o .= paginate($a);
+
+ return $o;
+ }
+
+
+ /**
+ * Plugins admin page
+ *
+ * @param App $a
+ * @return string
+ */
+ function admin_page_plugins(&$a){
+
+ /*
+ * Single plugin
+ */
+ if (\App::$argc == 3){
+ $plugin = \App::$argv[2];
+ if (!is_file("addon/$plugin/$plugin.php")){
+ notice( t("Item not found.") );
+ return '';
+ }
+
+ $enabled = in_array($plugin,\App::$plugins);
+ $info = get_plugin_info($plugin);
+ $x = check_plugin_versions($info);
+
+ // disable plugins which are installed but incompatible versions
+
+ if($enabled && ! $x) {
+ $enabled = false;
+ $idz = array_search($plugin, \App::$plugins);
+ if ($idz !== false) {
+ unset(\App::$plugins[$idz]);
+ uninstall_plugin($plugin);
+ set_config("system","addon", implode(", ",\App::$plugins));
+ }
+ }
+ $info['disabled'] = 1-intval($x);
+
+ if (x($_GET,"a") && $_GET['a']=="t"){
+ check_form_security_token_redirectOnErr('/admin/plugins', 'admin_plugins', 't');
+
+ // Toggle plugin status
+ $idx = array_search($plugin, \App::$plugins);
+ if ($idx !== false){
+ unset(\App::$plugins[$idx]);
+ uninstall_plugin($plugin);
+ info( sprintf( t("Plugin %s disabled."), $plugin ) );
+ } else {
+ \App::$plugins[] = $plugin;
+ install_plugin($plugin);
+ info( sprintf( t("Plugin %s enabled."), $plugin ) );
+ }
+ set_config("system","addon", implode(", ",\App::$plugins));
+ goaway(z_root() . '/admin/plugins' );
+ }
+ // display plugin details
+ require_once('library/markdown.php');
+
+ if (in_array($plugin, \App::$plugins)){
+ $status = 'on';
+ $action = t('Disable');
+ } else {
+ $status = 'off';
+ $action = t('Enable');
+ }
+
+ $readme = null;
+ if (is_file("addon/$plugin/README.md")){
+ $readme = file_get_contents("addon/$plugin/README.md");
+ $readme = Markdown($readme);
+ } else if (is_file("addon/$plugin/README")){
+ $readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>";
+ }
+
+ $admin_form = '';
+
+ $r = q("select * from addon where plugin_admin = 1 and name = '%s' limit 1",
+ dbesc($plugin)
+ );
+
+ if($r) {
+ @require_once("addon/$plugin/$plugin.php");
+ if(function_exists($plugin.'_plugin_admin')) {
+ $func = $plugin.'_plugin_admin';
+ $func($a, $admin_form);
+ }
+ }
+
+
+ $t = get_markup_template('admin_plugins_details.tpl');
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Plugins'),
+ '$toggle' => t('Toggle'),
+ '$settings' => t('Settings'),
+ '$baseurl' => z_root(),
+
+ '$plugin' => $plugin,
+ '$status' => $status,
+ '$action' => $action,
+ '$info' => $info,
+ '$str_author' => t('Author: '),
+ '$str_maintainer' => t('Maintainer: '),
+ '$str_minversion' => t('Minimum project version: '),
+ '$str_maxversion' => t('Maximum project version: '),
+ '$str_minphpversion' => t('Minimum PHP version: '),
+ '$str_requires' => t('Requires: '),
+ '$disabled' => t('Disabled - version incompatibility'),
+
+ '$admin_form' => $admin_form,
+ '$function' => 'plugins',
+ '$screenshot' => '',
+ '$readme' => $readme,
+
+ '$form_security_token' => get_form_security_token('admin_plugins'),
+ ));
+ }
+
+
+ /*
+ * List plugins
+ */
+ $plugins = array();
+ $files = glob('addon/*/');
+ if($files) {
+ foreach($files as $file) {
+ if (is_dir($file)){
+ list($tmp, $id) = array_map('trim', explode('/', $file));
+ $info = get_plugin_info($id);
+ $enabled = in_array($id,\App::$plugins);
+ $x = check_plugin_versions($info);
+
+ // disable plugins which are installed but incompatible versions
+
+ if($enabled && ! $x) {
+ $enabled = false;
+ $idz = array_search($id, \App::$plugins);
+ if ($idz !== false) {
+ unset(\App::$plugins[$idz]);
+ uninstall_plugin($id);
+ set_config("system","addon", implode(", ",\App::$plugins));
+ }
+ }
+ $info['disabled'] = 1-intval($x);
+
+ $plugins[] = array( $id, (($enabled)?"on":"off") , $info);
+ }
+ }
+ }
+
+ $t = get_markup_template('admin_plugins.tpl');
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Plugins'),
+ '$submit' => t('Submit'),
+ '$baseurl' => z_root(),
+ '$function' => 'plugins',
+ '$plugins' => $plugins,
+ '$disabled' => t('Disabled - version incompatibility'),
+ '$form_security_token' => get_form_security_token('admin_plugins'),
+ ));
+ }
+
+ /**
+ * @param array $themes
+ * @param string $th
+ * @param int $result
+ */
+ function toggle_theme(&$themes, $th, &$result) {
+ for($x = 0; $x < count($themes); $x ++) {
+ if($themes[$x]['name'] === $th) {
+ if($themes[$x]['allowed']) {
+ $themes[$x]['allowed'] = 0;
+ $result = 0;
+ }
+ else {
+ $themes[$x]['allowed'] = 1;
+ $result = 1;
+ }
+ }
+ }
+ }
+
+ /**
+ * @param array $themes
+ * @param string $th
+ * @return int
+ */
+ function theme_status($themes, $th) {
+ for($x = 0; $x < count($themes); $x ++) {
+ if($themes[$x]['name'] === $th) {
+ if($themes[$x]['allowed']) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+ }
+ return 0;
+ }
+
+
+ /**
+ * @param array $themes
+ * @return string
+ */
+ function rebuild_theme_table($themes) {
+ $o = '';
+ if(count($themes)) {
+ foreach($themes as $th) {
+ if($th['allowed']) {
+ if(strlen($o))
+ $o .= ',';
+ $o .= $th['name'];
+ }
+ }
+ }
+ return $o;
+ }
+
+
+ /**
+ * @brief Themes admin page.
+ *
+ * @param App &$a
+ * @return string
+ */
+ function admin_page_themes(&$a){
+
+ $allowed_themes_str = get_config('system', 'allowed_themes');
+ $allowed_themes_raw = explode(',', $allowed_themes_str);
+ $allowed_themes = array();
+ if(count($allowed_themes_raw))
+ foreach($allowed_themes_raw as $x)
+ if(strlen(trim($x)))
+ $allowed_themes[] = trim($x);
+
+ $themes = array();
+ $files = glob('view/theme/*');
+ if($files) {
+ foreach($files as $file) {
+ $f = basename($file);
+ $is_experimental = intval(file_exists($file . '/.experimental'));
+ $is_supported = 1-(intval(file_exists($file . '/.unsupported'))); // Is not used yet
+ $is_allowed = intval(in_array($f,$allowed_themes));
+ $themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed);
+ }
+ }
+
+ if(! count($themes)) {
+ notice( t('No themes found.'));
+ return '';
+ }
+
+ /*
+ * Single theme
+ */
+
+ if (\App::$argc == 3){
+ $theme = \App::$argv[2];
+ if(! is_dir("view/theme/$theme")){
+ notice( t("Item not found.") );
+ return '';
+ }
+
+ if (x($_GET,"a") && $_GET['a']=="t"){
+ check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't');
+
+ // Toggle theme status
+
+ toggle_theme($themes, $theme, $result);
+ $s = rebuild_theme_table($themes);
+ if($result)
+ info( sprintf('Theme %s enabled.', $theme));
+ else
+ info( sprintf('Theme %s disabled.', $theme));
+
+ set_config('system', 'allowed_themes', $s);
+ goaway(z_root() . '/admin/themes' );
+ }
+
+ // display theme details
+ require_once('library/markdown.php');
+
+ if (theme_status($themes,$theme)) {
+ $status="on"; $action= t("Disable");
+ } else {
+ $status="off"; $action= t("Enable");
+ }
+
+ $readme=Null;
+ if (is_file("view/theme/$theme/README.md")){
+ $readme = file_get_contents("view/theme/$theme/README.md");
+ $readme = Markdown($readme);
+ } else if (is_file("view/theme/$theme/README")){
+ $readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>";
+ }
+
+ $admin_form = '';
+ if (is_file("view/theme/$theme/php/config.php")){
+ require_once("view/theme/$theme/php/config.php");
+ if(function_exists("theme_admin")){
+ $admin_form = theme_admin($a);
+ }
+ }
+
+ $screenshot = array( get_theme_screenshot($theme), t('Screenshot'));
+ if(! stristr($screenshot[0],$theme))
+ $screenshot = null;
+
+ $t = get_markup_template('admin_plugins_details.tpl');
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Themes'),
+ '$toggle' => t('Toggle'),
+ '$settings' => t('Settings'),
+ '$baseurl' => z_root(),
+
+ '$plugin' => $theme,
+ '$status' => $status,
+ '$action' => $action,
+ '$info' => get_theme_info($theme),
+ '$function' => 'themes',
+ '$admin_form' => $admin_form,
+ '$str_author' => t('Author: '),
+ '$str_maintainer' => t('Maintainer: '),
+ '$screenshot' => $screenshot,
+ '$readme' => $readme,
+
+ '$form_security_token' => get_form_security_token('admin_themes'),
+ ));
+ }
+
+ /*
+ * List themes
+ */
+
+ $xthemes = array();
+ if($themes) {
+ foreach($themes as $th) {
+ $xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name']));
+ }
+ }
+
+ $t = get_markup_template('admin_plugins.tpl');
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Themes'),
+ '$submit' => t('Submit'),
+ '$baseurl' => z_root(),
+ '$function' => 'themes',
+ '$plugins' => $xthemes,
+ '$experimental' => t('[Experimental]'),
+ '$unsupported' => t('[Unsupported]'),
+ '$form_security_token' => get_form_security_token('admin_themes'),
+ ));
+ }
+
+
+ /**
+ * @brief POST handler for logs admin page.
+ *
+ * @param App &$a
+ */
+ function admin_page_logs_post(&$a) {
+ if (x($_POST, 'page_logs')) {
+ check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs');
+
+ $logfile = ((x($_POST,'logfile')) ? notags(trim($_POST['logfile'])) : '');
+ $debugging = ((x($_POST,'debugging')) ? true : false);
+ $loglevel = ((x($_POST,'loglevel')) ? intval(trim($_POST['loglevel'])) : 0);
+
+ set_config('system','logfile', $logfile);
+ set_config('system','debugging', $debugging);
+ set_config('system','loglevel', $loglevel);
+ }
+
+ info( t('Log settings updated.') );
+ goaway(z_root() . '/admin/logs' );
+ }
+
+ /**
+ * @brief Logs admin page.
+ *
+ * @param App $a
+ * @return string
+ */
+ function admin_page_logs(&$a){
+
+ $log_choices = Array(
+ LOGGER_NORMAL => 'Normal',
+ LOGGER_TRACE => 'Trace',
+ LOGGER_DEBUG => 'Debug',
+ LOGGER_DATA => 'Data',
+ LOGGER_ALL => 'All'
+ );
+
+ $t = get_markup_template('admin_logs.tpl');
+
+ $f = get_config('system', 'logfile');
+
+ $data = '';
+
+ if(!file_exists($f)) {
+ $data = t("Error trying to open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f exist and is
+ readable.");
+ }
+ else {
+ $fp = fopen($f, 'r');
+ if(!$fp) {
+ $data = t("Couldn't open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f is readable.");
+ }
+ else {
+ $fstat = fstat($fp);
+ $size = $fstat['size'];
+ if($size != 0)
+ {
+ if($size > 5000000 || $size < 0)
+ $size = 5000000;
+ $seek = fseek($fp,0-$size,SEEK_END);
+ if($seek === 0) {
+ $data = escape_tags(fread($fp,$size));
+ while(! feof($fp))
+ $data .= escape_tags(fread($fp,4096));
+ }
+ }
+ fclose($fp);
+ }
+ }
+
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Logs'),
+ '$submit' => t('Submit'),
+ '$clear' => t('Clear'),
+ '$data' => $data,
+ '$baseurl' => z_root(),
+ '$logname' => get_config('system','logfile'),
+
+ // name, label, value, help string, extra data...
+ '$debugging' => array('debugging', t("Debugging"),get_config('system','debugging'), ""),
+ '$logfile' => array('logfile', t("Log file"), get_config('system','logfile'), t("Must be writable by web server. Relative to your Red top-level directory.")),
+ '$loglevel' => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices),
+
+ '$form_security_token' => get_form_security_token('admin_logs'),
+ ));
+ }
+
+ function admin_page_profs_post(&$a) {
+
+ if(array_key_exists('basic',$_REQUEST)) {
+ $arr = explode(',',$_REQUEST['basic']);
+ for($x = 0; $x < count($arr); $x ++)
+ if(trim($arr[$x]))
+ $arr[$x] = trim($arr[$x]);
+ set_config('system','profile_fields_basic',$arr);
+
+ if(array_key_exists('advanced',$_REQUEST)) {
+ $arr = explode(',',$_REQUEST['advanced']);
+ for($x = 0; $x < count($arr); $x ++)
+ if(trim($arr[$x]))
+ $arr[$x] = trim($arr[$x]);
+ set_config('system','profile_fields_advanced',$arr);
+ }
+ goaway(z_root() . '/admin/profs');
+ }
+
+
+ if(array_key_exists('field_name',$_REQUEST)) {
+ if($_REQUEST['id']) {
+ $r = q("update profdef set field_name = '%s', field_type = '%s', field_desc = '%s' field_help = '%s', field_inputs = '%s' where id = %d",
+ dbesc($_REQUEST['field_name']),
+ dbesc($_REQUEST['field_type']),
+ dbesc($_REQUEST['field_desc']),
+ dbesc($_REQUEST['field_help']),
+ dbesc($_REQUEST['field_inputs']),
+ intval($_REQUEST['id'])
+ );
+ }
+ else {
+ $r = q("insert into profdef ( field_name, field_type, field_desc, field_help, field_inputs ) values ( '%s' , '%s', '%s', '%s', '%s' )",
+ dbesc($_REQUEST['field_name']),
+ dbesc($_REQUEST['field_type']),
+ dbesc($_REQUEST['field_desc']),
+ dbesc($_REQUEST['field_help']),
+ dbesc($_REQUEST['field_inputs'])
+ );
+ }
+ }
+
+
+ // add to chosen array basic or advanced
+
+ goaway(z_root() . '/admin/profs');
+ }
+
+ function admin_page_profs(&$a) {
+
+ if((argc() > 3) && argv(2) == 'drop' && intval(argv(3))) {
+ $r = q("delete from profdef where id = %d",
+ intval(argv(3))
+ );
+ // remove from allowed fields
+
+ goaway(z_root() . '/admin/profs');
+ }
+
+ if((argc() > 2) && argv(2) === 'new') {
+ return replace_macros(get_markup_template('profdef_edit.tpl'),array(
+ '$header' => t('New Profile Field'),
+ '$field_name' => array('field_name',t('Field nickname'),$_REQUEST['field_name'],t('System name of field')),
+ '$field_type' => array('field_type',t('Input type'),(($_REQUEST['field_type']) ? $_REQUEST['field_type'] : 'text'),''),
+ '$field_desc' => array('field_desc',t('Field Name'),$_REQUEST['field_desc'],t('Label on profile pages')),
+ '$field_help' => array('field_help',t('Help text'),$_REQUEST['field_help'],t('Additional info (optional)')),
+ '$submit' => t('Save')
+ ));
+ }
+
+ if((argc() > 2) && intval(argv(2))) {
+ $r = q("select * from profdef where id = %d limit 1",
+ intval(argv(2))
+ );
+ if(! $r) {
+ notice( t('Field definition not found') . EOL);
+ goaway(z_root() . '/admin/profs');
+ }
+
+ return replace_macros(get_markup_template('profdef_edit.tpl'),array(
+ '$id' => intval($r[0]['id']),
+ '$header' => t('Edit Profile Field'),
+ '$field_name' => array('field_name',t('Field nickname'),$r[0]['field_name'],t('System name of field')),
+ '$field_type' => array('field_type',t('Input type'),$r[0]['field_type'],''),
+ '$field_desc' => array('field_desc',t('Field Name'),$r[0]['field_desc'],t('Label on profile pages')),
+ '$field_help' => array('field_help',t('Help text'),$r[0]['field_help'],t('Additional info (optional)')),
+ '$submit' => t('Save')
+ ));
+ }
+
+ $basic = '';
+ $barr = array();
+ $fields = get_profile_fields_basic();
+ if(! $fields)
+ $fields = get_profile_fields_basic(1);
+ if($fields) {
+ foreach($fields as $k => $v) {
+ if($basic)
+ $basic .= ', ';
+ $basic .= trim($k);
+ $barr[] = trim($k);
+ }
+ }
+
+ $advanced = '';
+ $fields = get_profile_fields_advanced();
+ if(! $fields)
+ $fields = get_profile_fields_advanced(1);
+ if($fields) {
+ foreach($fields as $k => $v) {
+ if(in_array(trim($k),$barr))
+ continue;
+ if($advanced)
+ $advanced .= ', ';
+ $advanced .= trim($k);
+ }
+ }
+
+ $all = '';
+ $fields = get_profile_fields_advanced(1);
+ if($fields) {
+ foreach($fields as $k => $v) {
+ if($all)
+ $all .= ', ';
+ $all .= trim($k);
+ }
+ }
+
+ $r = q("select * from profdef where true");
+ if($r) {
+ foreach($r as $rr) {
+ if($all)
+ $all .= ', ';
+ $all .= $rr['field_name'];
+ }
+ }
+
+
+ $o = replace_macros(get_markup_template('admin_profiles.tpl'),array(
+ '$title' => t('Profile Fields'),
+ '$basic' => array('basic',t('Basic Profile Fields'),$basic,''),
+ '$advanced' => array('advanced',t('Advanced Profile Fields'),$advanced,t('(In addition to basic fields)')),
+ '$all' => $all,
+ '$all_desc' => t('All available fields'),
+ '$cust_field_desc' => t('Custom Fields'),
+ '$cust_fields' => $r,
+ '$edit' => t('Edit'),
+ '$drop' => t('Delete'),
+ '$new' => t('Create Custom Field'),
+ '$submit' => t('Submit')
+ ));
+
+ return $o;
+
+
+ }
+
+}
diff --git a/Zotlabs/Module/Api.php b/Zotlabs/Module/Api.php
new file mode 100644
index 000000000..3e7f23b6c
--- /dev/null
+++ b/Zotlabs/Module/Api.php
@@ -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];
+ }
+
+
+
+
+}
diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php
new file mode 100644
index 000000000..96e4cdd87
--- /dev/null
+++ b/Zotlabs/Module/Appman.php
@@ -0,0 +1,108 @@
+<?php
+namespace Zotlabs\Module; /** @file */
+
+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']),
+ 'sig' => escape_tags($_REQUEST['sig'])
+ );
+
+ $_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];
+ $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')),
+ '$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'] : ''), ''),
+ '$embed' => $embed,
+ '$submit' => t('Submit')
+ ));
+
+ }
+
+}
diff --git a/Zotlabs/Module/Apps.php b/Zotlabs/Module/Apps.php
new file mode 100644
index 000000000..4066966ca
--- /dev/null
+++ b/Zotlabs/Module/Apps.php
@@ -0,0 +1,46 @@
+<?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();
+
+ $syslist = get_system_apps();
+
+ if(local_channel()) {
+ $list = app_list(local_channel());
+ if($list) {
+ foreach($list as $x) {
+ $syslist[] = app_encode($x);
+ }
+ }
+ }
+ 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'),
+ '$title' => t('Apps'),
+ '$apps' => $apps,
+ ));
+
+ }
+
+}
diff --git a/Zotlabs/Module/Attach.php b/Zotlabs/Module/Attach.php
new file mode 100644
index 000000000..8948b66d7
--- /dev/null
+++ b/Zotlabs/Module/Attach.php
@@ -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();
+
+ }
+
+}
diff --git a/Zotlabs/Module/Authtest.php b/Zotlabs/Module/Authtest.php
new file mode 100644
index 000000000..239ae3bdb
--- /dev/null
+++ b/Zotlabs/Module/Authtest.php
@@ -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);
+ }
+
+}
diff --git a/Zotlabs/Module/Block.php b/Zotlabs/Module/Block.php
new file mode 100644
index 000000000..062befdb5
--- /dev/null
+++ b/Zotlabs/Module/Block.php
@@ -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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Blocks.php b/Zotlabs/Module/Blocks.php
new file mode 100644
index 000000000..192a4aded
--- /dev/null
+++ b/Zotlabs/Module/Blocks.php
@@ -0,0 +1,172 @@
+<?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'));
+
+ if(! $mimetype) {
+ $mimetype = 'choose';
+ }
+
+ $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,
+ '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;
+ }
+
+}
diff --git a/Zotlabs/Module/Bookmarks.php b/Zotlabs/Module/Bookmarks.php
new file mode 100644
index 000000000..733bfd4e3
--- /dev/null
+++ b/Zotlabs/Module/Bookmarks.php
@@ -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;
+
+ }
+
+
+}
diff --git a/Zotlabs/Module/Branchtopic.php b/Zotlabs/Module/Branchtopic.php
new file mode 100644
index 000000000..87a1a43e9
--- /dev/null
+++ b/Zotlabs/Module/Branchtopic.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php
new file mode 100644
index 000000000..89967bca1
--- /dev/null
+++ b/Zotlabs/Module/Cal.php
@@ -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 ispublic = '" . t('everybody') . "'; 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;
+ }
+
+ }
+
+}
diff --git a/mod/channel.php b/Zotlabs/Module/Channel.php
index 9bc7332dc..36f13e775 100644
--- a/mod/channel.php
+++ b/Zotlabs/Module/Channel.php
@@ -1,4 +1,6 @@
<?php
+namespace Zotlabs\Module;
+
require_once('include/contact_widgets.php');
require_once('include/items.php');
@@ -8,15 +10,16 @@ require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/permissions.php');
+class Channel extends \Zotlabs\Web\Controller {
-function channel_init(&$a) {
+function init() {
$which = null;
if(argc() > 1)
$which = argv(1);
if(! $which) {
if(local_channel()) {
- $channel = App::get_channel();
+ $channel = \App::get_channel();
if($channel && $channel['channel_address'])
$which = $channel['channel_address'];
}
@@ -27,19 +30,19 @@ function channel_init(&$a) {
}
$profile = 0;
- $channel = App::get_channel();
+ $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" ;
+ \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" ;
+// \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
@@ -48,13 +51,13 @@ function channel_init(&$a) {
}
-function channel_content(&$a, $update = 0, $load = false) {
+function get($update = 0, $load = false) {
if($load)
$_SESSION['loadtime'] = datetime_convert();
- $checkjs = new Zotlabs\Web\CheckJS();
+ $checkjs = new \Zotlabs\Web\CheckJS(1);
$category = $datequery = $datequery2 = '';
@@ -76,27 +79,27 @@ function channel_content(&$a, $update = 0, $load = false) {
if($update) {
// Ensure we've got a profile owner if updating.
- App::$profile['profile_uid'] = App::$profile_uid = $update;
+ \App::$profile['profile_uid'] = \App::$profile_uid = $update;
}
else {
- if(App::$profile['profile_uid'] == local_channel()) {
+ if(\App::$profile['profile_uid'] == local_channel()) {
nav_set_selected('home');
}
}
- $is_owner = (((local_channel()) && (App::$profile['profile_uid'] == local_channel())) ? true : false);
+ $is_owner = (((local_channel()) && (\App::$profile['profile_uid'] == local_channel())) ? true : false);
- $channel = App::get_channel();
- $observer = App::get_observer();
+ $channel = \App::get_channel();
+ $observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
- $perms = get_all_perms(App::$profile['profile_uid'],$ob_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']);
+ goaway (z_root() . "/profile/" . \App::$profile['channel_address']);
}
notice( t('Permission denied.') . EOL);
return;
@@ -105,9 +108,9 @@ function channel_content(&$a, $update = 0, $load = false) {
if(! $update) {
- $o .= profile_tabs($a, $is_owner, App::$profile['channel_address']);
+ $o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
- $o .= common_friends_visitor_widget(App::$profile['profile_uid']);
+ $o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
if($channel && $is_owner) {
$channel_acl = array(
@@ -125,15 +128,15 @@ function channel_content(&$a, $update = 0, $load = false) {
$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,((App::$profile['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : '')) : ''),
+ '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,((\App::$profile['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : '')) : ''),
'showacl' => (($is_owner) ? 'yes' : ''),
'bang' => '',
'visitor' => (($is_owner || $observer) ? true : false),
- 'profile_uid' => App::$profile['profile_uid'],
+ 'profile_uid' => \App::$profile['profile_uid'],
'editor_autocomplete' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
@@ -150,18 +153,18 @@ function channel_content(&$a, $update = 0, $load = false) {
*/
$item_normal = item_normal();
- $sql_extra = item_permissions_sql(App::$profile['profile_uid']);
+ $sql_extra = item_permissions_sql(\App::$profile['profile_uid']);
- if(get_pconfig(App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid))
+ 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']) . " ";
+ $abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " ";
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
- App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string) . '" title="oembed" />' . "\r\n";
+ \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string) . '" title="oembed" />' . "\r\n";
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
@@ -174,7 +177,7 @@ function channel_content(&$a, $update = 0, $load = false) {
$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'])
+ intval(\App::$profile['profile_uid'])
);
} else {
$r = q("SELECT distinct parent AS `item_id`, created from item
@@ -184,7 +187,7 @@ function channel_content(&$a, $update = 0, $load = false) {
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra
ORDER BY created DESC",
- intval(App::$profile['profile_uid'])
+ intval(\App::$profile['profile_uid'])
);
$_SESSION['loadtime'] = datetime_convert();
}
@@ -207,15 +210,15 @@ function channel_content(&$a, $update = 0, $load = false) {
}
$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']));
+ \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'])
+ intval(\App::$profile['profile_uid'])
);
if (! $r) {
notice( t('Permission denied.') . EOL);
@@ -229,7 +232,7 @@ function channel_content(&$a, $update = 0, $load = false) {
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'])
+ intval(\App::$profile['profile_uid'])
);
}
}
@@ -247,7 +250,7 @@ function channel_content(&$a, $update = 0, $load = false) {
WHERE `item`.`uid` = %d $item_normal
AND `item`.`parent` IN ( %s )
$sql_extra ",
- intval(App::$profile['profile_uid']),
+ intval(\App::$profile['profile_uid']),
dbesc($parents_str)
);
@@ -270,19 +273,19 @@ function channel_content(&$a, $update = 0, $load = false) {
// 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');
+ $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']
+ $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(
+ \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'),
+ '$uid' => ((\App::$profile['profile_uid']) ? \App::$profile['profile_uid'] : '0'),
'$gid' => '0',
'$cid' => '0',
'$cmin' => '0',
@@ -294,7 +297,7 @@ function channel_content(&$a, $update = 0, $load = false) {
'$nouveau' => '0',
'$wall' => '1',
'$fh' => '0',
- '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
+ '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => '',
'$order' => '',
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
@@ -348,7 +351,7 @@ function channel_content(&$a, $update = 0, $load = false) {
if((! $update) || ($checkjs->disabled())) {
$o .= alt_pager($a,count($items));
if ($mid && $items[0]['title'])
- App::$page['title'] = $items[0]['title'] . " - " . App::$page['title'];
+ \App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
}
if($mid)
@@ -356,3 +359,6 @@ function channel_content(&$a, $update = 0, $load = false) {
return $o;
}
+
+
+} \ No newline at end of file
diff --git a/Zotlabs/Module/Chanview.php b/Zotlabs/Module/Chanview.php
new file mode 100644
index 000000000..f70444816
--- /dev/null
+++ b/Zotlabs/Module/Chanview.php
@@ -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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php
new file mode 100644
index 000000000..9508ed3de
--- /dev/null
+++ b/Zotlabs/Module/Chat.php
@@ -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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Chatsvc.php b/Zotlabs/Module/Chatsvc.php
new file mode 100644
index 000000000..a9bc97301
--- /dev/null
+++ b/Zotlabs/Module/Chatsvc.php
@@ -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);
+
+ }
+
+
+}
diff --git a/Zotlabs/Module/Cloud.php b/Zotlabs/Module/Cloud.php
new file mode 100644
index 000000000..5f40f4af1
--- /dev/null
+++ b/Zotlabs/Module/Cloud.php
@@ -0,0 +1,110 @@
+<?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.');
+ }
+ }
+ }
+
+ // require_once('\Zotlabs/Storage/Browser.php');
+ // 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();
+ }
+
+}
diff --git a/Zotlabs/Module/Common.php b/Zotlabs/Module/Common.php
new file mode 100644
index 000000000..1c428d256
--- /dev/null
+++ b/Zotlabs/Module/Common.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Connect.php b/Zotlabs/Module/Connect.php
new file mode 100644
index 000000000..6ef3577d7
--- /dev/null
+++ b/Zotlabs/Module/Connect.php
@@ -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;
+ }
+}
diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php
new file mode 100644
index 000000000..564f4e527
--- /dev/null
+++ b/Zotlabs/Module/Connections.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php
new file mode 100644
index 000000000..2b524096f
--- /dev/null
+++ b/Zotlabs/Module/Connedit.php
@@ -0,0 +1,762 @@
+<?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;
+
+ $buttons = 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.'),
+ '$buttons' => (($self) ? '' : $buttons),
+ '$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'];
+
+ }
+
+
+ }
+
+}
diff --git a/Zotlabs/Module/Contactgroup.php b/Zotlabs/Module/Contactgroup.php
new file mode 100644
index 000000000..497442ff4
--- /dev/null
+++ b/Zotlabs/Module/Contactgroup.php
@@ -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();
+ }
+}
diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php
new file mode 100644
index 000000000..aafc1bdb0
--- /dev/null
+++ b/Zotlabs/Module/Cover_photo.php
@@ -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;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Dav.php b/Zotlabs/Module/Dav.php
new file mode 100644
index 000000000..42eb3d0c1
--- /dev/null
+++ b/Zotlabs/Module/Dav.php
@@ -0,0 +1,150 @@
+<?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();
+
+ $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);
+
+ // 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();
+ }
+
+}
diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php
new file mode 100644
index 000000000..b8bac53bb
--- /dev/null
+++ b/Zotlabs/Module/Directory.php
@@ -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;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Dirsearch.php b/Zotlabs/Module/Dirsearch.php
new file mode 100644
index 000000000..8f60910f1
--- /dev/null
+++ b/Zotlabs/Module/Dirsearch.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php
new file mode 100644
index 000000000..2a5a04a2a
--- /dev/null
+++ b/Zotlabs/Module/Display.php
@@ -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 );
+ }
+
+ }
+ */
+ }
+
+
+}
diff --git a/Zotlabs/Module/Dreport.php b/Zotlabs/Module/Dreport.php
new file mode 100644
index 000000000..e8709c952
--- /dev/null
+++ b/Zotlabs/Module/Dreport.php
@@ -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));
+ }
+
+}
diff --git a/Zotlabs/Module/Editblock.php b/Zotlabs/Module/Editblock.php
new file mode 100644
index 000000000..90016952e
--- /dev/null
+++ b/Zotlabs/Module/Editblock.php
@@ -0,0 +1,198 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/identity.php');
+require_once('include/acl_selectors.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;
+ }
+
+ $plaintext = true;
+
+ $mimeselect = '';
+ $mimetype = $itm[0]['mimetype'];
+
+ if($mimetype != 'text/bbcode')
+ $plaintext = true;
+
+ if(get_config('system','page_mimetype'))
+ $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />';
+ else
+ $mimeselect = mimetype_select($itm[0]['uid'],$mimetype);
+
+ \App::$page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array(
+ '$baseurl' => z_root(),
+ '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
+ '$pretext' => '',
+ '$ispublic' => '&nbsp;', // t('Visible to <strong>everybody</strong>'),
+ '$geotag' => '',
+ '$nickname' => $channel['channel_address'],
+ '$confirmdelete' => t('Delete block?'),
+ '$bbco_autocomplete'=> (($mimetype == 'text/bbcode') ? 'bbcode' : 'comanche-block')
+ ));
+
+ $tpl = get_markup_template("jot.tpl");
+
+ $jotplugins = '';
+ $jotnets = '';
+
+ call_hooks('jot_tool', $jotplugins);
+ call_hooks('jot_networks', $jotnets);
+
+ $rp = 'blocks/' . $channel['channel_address'];
+
+ $editor = replace_macros($tpl,array(
+ '$return_path' => $rp,
+ '$action' => 'item',
+ '$webpage' => ITEM_TYPE_BLOCK,
+ '$share' => t('Edit'),
+ '$bold' => t('Bold'),
+ '$italic' => t('Italic'),
+ '$underline' => t('Underline'),
+ '$quote' => t('Quote'),
+ '$code' => t('Code'),
+ '$writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_storage'),
+ '$upload' => t('Upload photo'),
+ '$attach' => t('Attach file'),
+ '$weblink' => t('Insert web link'),
+ '$youtube' => t('Insert YouTube video'),
+ '$video' => t('Insert Vorbis [.ogg] video'),
+ '$audio' => t('Insert Vorbis [.ogg] audio'),
+ '$setloc' => t('Set your location'),
+ '$noloc' => t('Clear browser location'),
+ '$wait' => t('Please wait'),
+ '$permset' => t('Permission settings'),
+ '$ptyp' => $itm[0]['type'],
+ '$mimeselect' => $mimeselect,
+ '$content' => undo_post_tagging($itm[0]['body']),
+ '$post_id' => $post_id,
+ '$baseurl' => z_root(),
+ '$defloc' => $channel['channel_location'],
+ '$visitor' => false,
+ '$public' => t('Public post'),
+ '$jotnets' => $jotnets,
+ '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
+ '$placeholdertitle' => t('Title (optional)'),
+ '$pagetitle' => $block_title,
+ '$category' => '',
+ '$placeholdercategory' => t('Categories (optional, comma-separated list)'),
+ '$emtitle' => t('Example: bob@example.com, mary@example.com'),
+ '$lockstate' => $lockstate,
+ '$acl' => '',
+ '$bang' => '',
+ '$profile_uid' => (intval($channel['channel_id'])),
+ '$preview' => t('Preview'),
+ '$jotplugins' => $jotplugins,
+ '$sourceapp' => $itm[0]['app'],
+ '$defexpire' => '',
+ '$feature_expire' => false,
+ '$expires' => t('Set expiration date'),
+ '$bbcode' => (($mimetype == 'text/bbcode') ? true : false)
+ ));
+
+ $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;
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Editlayout.php b/Zotlabs/Module/Editlayout.php
new file mode 100644
index 000000000..cec55f5cc
--- /dev/null
+++ b/Zotlabs/Module/Editlayout.php
@@ -0,0 +1,195 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/identity.php');
+require_once('include/acl_selectors.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'];
+
+ $plaintext = true;
+
+ \App::$page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array(
+ '$baseurl' => z_root(),
+ '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
+ '$pretext' => '',
+ '$ispublic' => '&nbsp;', // t('Visible to <strong>everybody</strong>'),
+ '$geotag' => $geotag,
+ '$nickname' => $channel['channel_address'],
+ '$confirmdelete' => t('Delete layout?'),
+ '$bbco_autocomplete'=> 'comanche'
+ ));
+
+
+ $tpl = get_markup_template("jot.tpl");
+
+ $jotplugins = '';
+ $jotnets = '';
+
+ call_hooks('jot_tool', $jotplugins);
+ call_hooks('jot_networks', $jotnets);
+
+
+ // FIXME A return path with $_SESSION doesn't always work for observer - it may WSoD
+ // instead of loading a sensible page. So, send folk to the webpage list.
+
+ $rp = 'layouts/' . $which;
+
+ $editor = replace_macros($tpl,array(
+ '$return_path' => $rp,
+ '$action' => 'item',
+ '$webpage' => ITEM_TYPE_PDL,
+ '$share' => t('Edit'),
+ '$bold' => t('Bold'),
+ '$italic' => t('Italic'),
+ '$underline' => t('Underline'),
+ '$quote' => t('Quote'),
+ '$code' => t('Code'),
+ '$upload' => t('Upload photo'),
+ '$attach' => t('Attach file'),
+ '$weblink' => t('Insert web link'),
+ '$youtube' => t('Insert YouTube video'),
+ '$video' => t('Insert Vorbis [.ogg] video'),
+ '$audio' => t('Insert Vorbis [.ogg] audio'),
+ '$setloc' => t('Set your location'),
+ '$noloc' => t('Clear browser location'),
+ '$wait' => t('Please wait'),
+ '$permset' => t('Permission settings'),
+ '$ptyp' => $itm[0]['type'],
+ '$content' => undo_post_tagging($itm[0]['body']),
+ '$post_id' => $post_id,
+ '$baseurl' => z_root(),
+ '$defloc' => $channel['channel_location'],
+ '$visitor' => false,
+ '$public' => t('Public post'),
+ '$jotnets' => $jotnets,
+ '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
+ '$placeholdertitle' => t('Layout Description (Optional)'),
+ '$pagetitle' => $layout_title,
+ '$placeholdpagetitle' => t('Layout Name'),
+ '$category' => '',
+ '$placeholdercategory' => t('Categories (optional, comma-separated list)'),
+ '$emtitle' => t('Example: bob@example.com, mary@example.com'),
+ '$lockstate' => $lockstate,
+ '$acl' => '',
+ '$bang' => '',
+ '$profile_uid' => (intval($owner)),
+ '$jotplugins' => $jotplugins,
+ '$sourceapp' => t(\App::$sourcename),
+ '$defexpire' => '',
+ '$feature_expire' => false,
+ '$expires' => t('Set expiration date'),
+ ));
+
+
+ $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;
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php
new file mode 100644
index 000000000..d8b971f6c
--- /dev/null
+++ b/Zotlabs/Module/Editpost.php
@@ -0,0 +1,181 @@
+<?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');
+
+
+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'];
+
+
+ $plaintext = true;
+ // if(feature_enabled(local_channel(),'richtext'))
+ // $plaintext = false;
+
+ $channel = \App::get_channel();
+
+ \App::$page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array(
+ '$baseurl' => z_root(),
+ '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
+ '$pretext' => '',
+ '$ispublic' => '&nbsp;', // t('Visible to <strong>everybody</strong>'),
+ '$geotag' => $geotag,
+ '$nickname' => $channel['channel_address'],
+ '$expireswhen' => t('Expires YYYY-MM-DD HH:MM'),
+ '$confirmdelete' => t('Delete item?'),
+ '$editor_autocomplete'=> true,
+ '$bbco_autocomplete'=> 'bbcode'
+ ));
+
+ 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);
+ }
+
+ $tpl = get_markup_template("jot.tpl");
+
+ $jotplugins = '';
+ $jotnets = '';
+
+ call_hooks('jot_tool', $jotplugins);
+ call_hooks('jot_networks', $jotnets);
+
+ //$tpl = replace_macros($tpl,array('$jotplugins' => $jotplugins));
+
+ $voting = feature_enabled($owner_uid,'consensus_tools');
+
+ $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";
+ }
+ }
+ }
+
+ $cipher = get_pconfig(\App::$profile['profile_uid'],'system','default_cipher');
+ if(! $cipher)
+ $cipher = 'aes256';
+
+
+ $editor = replace_macros($tpl,array(
+ '$return_path' => $_SESSION['return_url'],
+ '$action' => 'item',
+ '$share' => t('Edit'),
+ '$bold' => t('Bold'),
+ '$italic' => t('Italic'),
+ '$underline' => t('Underline'),
+ '$quote' => t('Quote'),
+ '$code' => t('Code'),
+ '$upload' => t('Upload photo'),
+ '$attach' => t('Attach file'),
+ '$weblink' => t('Insert web link'),
+ '$youtube' => t('Insert YouTube video'),
+ '$video' => t('Insert Vorbis [.ogg] video'),
+ '$audio' => t('Insert Vorbis [.ogg] audio'),
+ '$setloc' => t('Set your location'),
+ '$noloc' => t('Clear browser location'),
+ '$voting' => t('Toggle voting'),
+ '$feature_voting' => $voting,
+ '$consensus' => intval($itm[0]['item_consensus']),
+ '$wait' => t('Please wait'),
+ '$permset' => t('Permission settings'),
+ '$ptyp' => $itm[0]['obj_type'],
+ '$content' => undo_post_tagging($itm[0]['body']),
+ '$post_id' => $post_id,
+ '$parent' => (($itm[0]['parent'] != $itm[0]['id']) ? $itm[0]['parent'] : ''),
+ '$baseurl' => z_root(),
+ '$defloc' => $channel['channel_location'],
+ '$visitor' => false,
+ '$public' => t('Public post'),
+ '$jotnets' => $jotnets,
+ '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
+ '$placeholdertitle' => t('Title (optional)'),
+ '$category' => $category,
+ '$placeholdercategory' => t('Categories (optional, comma-separated list)'),
+ '$emtitle' => t('Example: bob@example.com, mary@example.com'),
+ '$lockstate' => $lockstate,
+ '$acl' => '',
+ '$bang' => '',
+ '$profile_uid' => $owner_uid,
+ '$preview' => t('Preview'),
+ '$jotplugins' => $jotplugins,
+ '$sourceapp' => t(\App::$sourcename),
+ '$catsenabled' => $catsenabled,
+ '$defexpire' => datetime_convert('UTC', date_default_timezone_get(),$itm[0]['expires']),
+ '$feature_expire' => ((feature_enabled(\App::$profile['profile_uid'],'content_expire') && (! $webpage)) ? true : false),
+ '$expires' => t('Set expiration date'),
+ '$feature_encrypt' => ((feature_enabled(\App::$profile['profile_uid'],'content_encrypt') && (! $webpage)) ? true : false),
+ '$encrypt' => t('Encrypt text'),
+ '$cipher' => $cipher,
+ '$expiryModalOK' => t('OK'),
+ '$expiryModalCANCEL' => t('Cancel'),
+ '$bbcode' => true
+ ));
+
+ $o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
+ '$title' => t('Edit post'),
+ '$editor' => $editor
+ ));
+
+ return $o;
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Editwebpage.php b/Zotlabs/Module/Editwebpage.php
new file mode 100644
index 000000000..01d9e8aad
--- /dev/null
+++ b/Zotlabs/Module/Editwebpage.php
@@ -0,0 +1,239 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/identity.php');
+require_once('include/acl_selectors.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'];
+
+ $plaintext = true;
+
+ $mimetype = $itm[0]['mimetype'];
+
+ if($mimetype === 'application/x-php') {
+ if((! $uid) || ($uid != $itm[0]['uid'])) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+ }
+
+ $mimeselect = '';
+
+ if($mimetype != 'text/bbcode')
+ $plaintext = true;
+
+ if(get_config('system','page_mimetype'))
+ $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />';
+ else
+ $mimeselect = mimetype_select($itm[0]['uid'],$mimetype);
+
+ $layout = get_config('system','page_layout');
+ if($layout)
+ $layoutselect = '<input type="hidden" name="layout_mid" value="' . $layout . '" />';
+ else
+ $layoutselect = layout_select($itm[0]['uid'],$itm[0]['layout_mid']);
+
+ \App::$page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array(
+ '$baseurl' => z_root(),
+ '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
+ '$pretext' => '',
+ '$ispublic' => '&nbsp;', // t('Visible to <strong>everybody</strong>'),
+ '$geotag' => $geotag,
+ '$nickname' => $channel['channel_address'],
+ '$confirmdelete' => t('Delete webpage?'),
+ '$bbco_autocomplete'=> (($mimetype == 'text/bbcode') ? 'bbcode' : '')
+ ));
+
+ $tpl = get_markup_template("jot.tpl");
+
+ $jotplugins = '';
+ $jotnets = '';
+
+ call_hooks('jot_tool', $jotplugins);
+ call_hooks('jot_networks', $jotnets);
+
+ // FIXME A return path with $_SESSION doesn't always work for observer - it may WSoD
+ // instead of loading a sensible page. So, send folk to the webpage list.
+
+ $rp = 'webpages/' . $which;
+
+ $editor = replace_macros($tpl,array(
+ '$return_path' => $rp,
+ '$webpage' => ITEM_TYPE_WEBPAGE,
+ '$placeholdpagetitle' => t('Page link title'),
+ '$pagetitle' => $page_title,
+ '$writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_storage'),
+ '$action' => 'item',
+ '$share' => t('Edit'),
+ '$bold' => t('Bold'),
+ '$italic' => t('Italic'),
+ '$underline' => t('Underline'),
+ '$quote' => t('Quote'),
+ '$code' => t('Code'),
+ '$upload' => t('Upload photo'),
+ '$attach' => t('Attach file'),
+ '$weblink' => t('Insert web link'),
+ '$youtube' => t('Insert YouTube video'),
+ '$video' => t('Insert Vorbis [.ogg] video'),
+ '$audio' => t('Insert Vorbis [.ogg] audio'),
+ '$setloc' => t('Set your location'),
+ '$noloc' => ((get_pconfig($uid, 'system', 'use_browser_location')) ? t('Clear browser location') : ''),
+ '$wait' => t('Please wait'),
+ '$permset' => t('Permission settings'),
+ '$ptyp' => $itm[0]['type'],
+ '$content' => undo_post_tagging($itm[0]['body']),
+ '$post_id' => $post_id,
+ '$baseurl' => z_root(),
+ '$defloc' => $itm[0]['location'],
+ '$visitor' => ($is_owner) ? true : false,
+ '$acl' => populate_acl($itm[0],false),
+ '$showacl' => ($is_owner) ? true : false,
+ '$public' => t('Public post'),
+ '$jotnets' => $jotnets,
+ '$mimeselect' => $mimeselect,
+ '$layoutselect' => $layoutselect,
+ '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
+ '$placeholdertitle' => t('Title (optional)'),
+ '$category' => '',
+ '$placeholdercategory' => t('Categories (optional, comma-separated list)'),
+ '$emtitle' => t('Example: bob@example.com, mary@example.com'),
+ 'lockstate' => (((strlen($itm[0]['allow_cid'])) || (strlen($itm[0]['allow_gid'])) || (strlen($itm[0]['deny_cid'])) || (strlen($itm[0]['deny_gid']))) ? 'lock' : 'unlock'),
+ '$bang' => '',
+ '$profile_uid' => (intval($owner)),
+ '$preview' => t('Preview'),
+ '$jotplugins' => $jotplugins,
+ '$sourceapp' => \App::$sourcename,
+ '$defexpire' => '',
+ '$feature_expire' => false,
+ '$expires' => t('Set expiration date'),
+ '$bbcode' => (($mimetype == 'text/bbcode') ? true : false)
+ ));
+
+ $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;
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Events.php b/Zotlabs/Module/Events.php
new file mode 100644
index 000000000..a14e320b2
--- /dev/null
+++ b/Zotlabs/Module/Events.php
@@ -0,0 +1,714 @@
+<?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');
+
+
+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'),
+ '$acl' => (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults),false)),
+ '$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');
+ }
+ }
+
+ }
+
+}
diff --git a/Zotlabs/Module/Fbrowser.php b/Zotlabs/Module/Fbrowser.php
new file mode 100644
index 000000000..eef3cb67d
--- /dev/null
+++ b/Zotlabs/Module/Fbrowser.php
@@ -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');
+ }
+
+
+}
diff --git a/Zotlabs/Module/Feed.php b/Zotlabs/Module/Feed.php
new file mode 100644
index 000000000..9d33ba2c3
--- /dev/null
+++ b/Zotlabs/Module/Feed.php
@@ -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();
+ }
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Ffsapi.php b/Zotlabs/Module/Ffsapi.php
new file mode 100644
index 000000000..f3ade73c2
--- /dev/null
+++ b/Zotlabs/Module/Ffsapi.php
@@ -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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Fhublocs.php b/Zotlabs/Module/Fhublocs.php
new file mode 100644
index 000000000..f5b439421
--- /dev/null
+++ b/Zotlabs/Module/Fhublocs.php
@@ -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;
+
+ }
+ }
+}
diff --git a/Zotlabs/Module/Filer.php b/Zotlabs/Module/Filer.php
new file mode 100644
index 000000000..607d088db
--- /dev/null
+++ b/Zotlabs/Module/Filer.php
@@ -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();
+ }
+
+}
diff --git a/Zotlabs/Module/Filerm.php b/Zotlabs/Module/Filerm.php
new file mode 100644
index 000000000..eb9a42c1e
--- /dev/null
+++ b/Zotlabs/Module/Filerm.php
@@ -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();
+ }
+
+}
diff --git a/Zotlabs/Module/Filestorage.php b/Zotlabs/Module/Filestorage.php
new file mode 100644
index 000000000..934a1e6a4
--- /dev/null
+++ b/Zotlabs/Module/Filestorage.php
@@ -0,0 +1,173 @@
+<?php
+namespace Zotlabs\Module;
+/**
+ * @file mod/filestorage.php
+ *
+ */
+
+require_once('include/attach.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);
+ $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);
+ }
+
+}
diff --git a/Zotlabs/Module/Follow.php b/Zotlabs/Module/Follow.php
new file mode 100644
index 000000000..d3114557b
--- /dev/null
+++ b/Zotlabs/Module/Follow.php
@@ -0,0 +1,65 @@
+<?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();
+
+ $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();
+ }
+ }
+}
diff --git a/Zotlabs/Module/Fsuggest.php b/Zotlabs/Module/Fsuggest.php
new file mode 100644
index 000000000..143fd34e1
--- /dev/null
+++ b/Zotlabs/Module/Fsuggest.php
@@ -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;
+ }
+}
diff --git a/Zotlabs/Module/Getfile.php b/Zotlabs/Module/Getfile.php
new file mode 100644
index 000000000..6999e77e8
--- /dev/null
+++ b/Zotlabs/Module/Getfile.php
@@ -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();
+
+
+
+ }
+}
diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php
new file mode 100644
index 000000000..144797baf
--- /dev/null
+++ b/Zotlabs/Module/Group.php
@@ -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);
+
+ }
+
+
+}
diff --git a/Zotlabs/Module/Hcard.php b/Zotlabs/Module/Hcard.php
new file mode 100644
index 000000000..2636e676b
--- /dev/null
+++ b/Zotlabs/Module/Hcard.php
@@ -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());
+
+
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Help.php b/Zotlabs/Module/Help.php
new file mode 100644
index 000000000..4842c56c6
--- /dev/null
+++ b/Zotlabs/Module/Help.php
@@ -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;
+ }
+
+ }
+
+
+}
diff --git a/Zotlabs/Module/Home.php b/Zotlabs/Module/Home.php
new file mode 100644
index 000000000..f3ba96fdd
--- /dev/null
+++ b/Zotlabs/Module/Home.php
@@ -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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Hostxrd.php b/Zotlabs/Module/Hostxrd.php
new file mode 100644
index 000000000..1aae8da9e
--- /dev/null
+++ b/Zotlabs/Module/Hostxrd.php
@@ -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();
+ }
+
+}
diff --git a/Zotlabs/Module/Id.php b/Zotlabs/Module/Id.php
new file mode 100644
index 000000000..6a94b57f5
--- /dev/null
+++ b/Zotlabs/Module/Id.php
@@ -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');
+ }
+ }
+
diff --git a/Zotlabs/Module/Impel.php b/Zotlabs/Module/Impel.php
new file mode 100644
index 000000000..e326f7818
--- /dev/null
+++ b/Zotlabs/Module/Impel.php
@@ -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);
+
+ }
+
+}
diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php
new file mode 100644
index 000000000..dadbf8ff1
--- /dev/null
+++ b/Zotlabs/Module/Import.php
@@ -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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Import_items.php b/Zotlabs/Module/Import_items.php
new file mode 100644
index 000000000..a862836c5
--- /dev/null
+++ b/Zotlabs/Module/Import_items.php
@@ -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;
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php
new file mode 100644
index 000000000..3d7438484
--- /dev/null
+++ b/Zotlabs/Module/Invite.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
new file mode 100644
index 000000000..74fbeed67
--- /dev/null
+++ b/Zotlabs/Module/Item.php
@@ -0,0 +1,1265 @@
+<?php
+namespace Zotlabs\Module;
+
+/**
+ *
+ * This is the POST destination for most all locally posted
+ * text stuff. This function handles status, wall-to-wall status,
+ * local comments, and remote coments that are posted on this site
+ * (as opposed to being delivered in a feed).
+ * Also processed here are posts and comments coming through the
+ * statusnet/twitter API.
+ * All of these become an "item" which is our basic unit of
+ * information.
+ * Posts that originate externally or do not fall into the above
+ * posting categories go through item_store() instead of this function.
+ *
+ */
+
+require_once('include/crypto.php');
+require_once('include/enotify.php');
+require_once('include/items.php');
+require_once('include/attach.php');
+
+
+class Item extends \Zotlabs\Web\Controller {
+
+ function post() {
+
+ // This will change. Figure out who the observer is and whether or not
+ // they have permission to post here. Else ignore the post.
+
+ if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'commenter')))
+ return;
+
+ require_once('include/security.php');
+
+ $uid = local_channel();
+ $channel = null;
+ $observer = null;
+
+
+ /**
+ * Is this a reply to something?
+ */
+
+ $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
+ $parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : '');
+
+ $remote_xchan = ((x($_REQUEST,'remote_xchan')) ? trim($_REQUEST['remote_xchan']) : false);
+ $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ dbesc($remote_xchan)
+ );
+ if($r)
+ $remote_observer = $r[0];
+ else
+ $remote_xchan = $remote_observer = false;
+
+ $profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0);
+ require_once('include/identity.php');
+ $sys = get_sys_channel();
+ if($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) {
+ $uid = intval($sys['channel_id']);
+ $channel = $sys;
+ $observer = $sys;
+ }
+
+ if(x($_REQUEST,'dropitems')) {
+ require_once('include/items.php');
+ $arr_drop = explode(',',$_REQUEST['dropitems']);
+ drop_items($arr_drop);
+ $json = array('success' => 1);
+ echo json_encode($json);
+ killme();
+ }
+
+ call_hooks('post_local_start', $_REQUEST);
+
+ // logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
+
+ $api_source = ((x($_REQUEST,'api_source') && $_REQUEST['api_source']) ? true : false);
+
+ $consensus = intval($_REQUEST['consensus']);
+
+ // 'origin' (if non-zero) indicates that this network is where the message originated,
+ // for the purpose of relaying comments to other conversation members.
+ // If using the API from a device (leaf node) you must set origin to 1 (default) or leave unset.
+ // If the API is used from another network with its own distribution
+ // and deliveries, you may wish to set origin to 0 or false and allow the other
+ // network to relay comments.
+
+ // If you are unsure, it is prudent (and important) to leave it unset.
+
+ $origin = (($api_source && array_key_exists('origin',$_REQUEST)) ? intval($_REQUEST['origin']) : 1);
+
+ // To represent message-ids on other networks - this will create an item_id record
+
+ $namespace = (($api_source && array_key_exists('namespace',$_REQUEST)) ? strip_tags($_REQUEST['namespace']) : '');
+ $remote_id = (($api_source && array_key_exists('remote_id',$_REQUEST)) ? strip_tags($_REQUEST['remote_id']) : '');
+
+ $owner_hash = null;
+
+ $message_id = ((x($_REQUEST,'message_id') && $api_source) ? strip_tags($_REQUEST['message_id']) : '');
+ $created = ((x($_REQUEST,'created')) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['created']) : datetime_convert());
+ $post_id = ((x($_REQUEST,'post_id')) ? intval($_REQUEST['post_id']) : 0);
+ $app = ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : '');
+ $return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : '');
+ $preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0);
+ $categories = ((x($_REQUEST,'category')) ? escape_tags($_REQUEST['category']) : '');
+ $webpage = ((x($_REQUEST,'webpage')) ? intval($_REQUEST['webpage']) : 0);
+ $pagetitle = ((x($_REQUEST,'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : '');
+ $layout_mid = ((x($_REQUEST,'layout_mid')) ? escape_tags($_REQUEST['layout_mid']): '');
+ $plink = ((x($_REQUEST,'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
+ $obj_type = ((x($_REQUEST,'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE);
+
+ // allow API to bulk load a bunch of imported items with sending out a bunch of posts.
+ $nopush = ((x($_REQUEST,'nopush')) ? intval($_REQUEST['nopush']) : 0);
+
+ /*
+ * Check service class limits
+ */
+ if ($uid && !(x($_REQUEST,'parent')) && !(x($_REQUEST,'post_id'))) {
+ $ret = $this->item_check_service_class($uid,(($_REQUEST['webpage'] == ITEM_TYPE_WEBPAGE) ? true : false));
+ if (!$ret['success']) {
+ notice( t($ret['message']) . EOL) ;
+ if(x($_REQUEST,'return'))
+ goaway(z_root() . "/" . $return_path );
+ killme();
+ }
+ }
+
+ if($pagetitle) {
+ require_once('library/urlify/URLify.php');
+ $pagetitle = strtolower(\URLify::transliterate($pagetitle));
+ }
+
+
+ $item_flags = $item_restrict = 0;
+
+ $route = '';
+ $parent_item = null;
+ $parent_contact = null;
+ $thr_parent = '';
+ $parid = 0;
+ $r = false;
+
+ if($parent || $parent_mid) {
+
+ if(! x($_REQUEST,'type'))
+ $_REQUEST['type'] = 'net-comment';
+
+ if($obj_type == ACTIVITY_OBJ_POST)
+ $obj_type = ACTIVITY_OBJ_COMMENT;
+
+ if($parent) {
+ $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1",
+ intval($parent)
+ );
+ }
+ elseif($parent_mid && $uid) {
+ // This is coming from an API source, and we are logged in
+ $r = q("SELECT * FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1",
+ dbesc($parent_mid),
+ intval($uid)
+ );
+ }
+ // if this isn't the real parent of the conversation, find it
+ if($r !== false && count($r)) {
+ $parid = $r[0]['parent'];
+ $parent_mid = $r[0]['mid'];
+ if($r[0]['id'] != $r[0]['parent']) {
+ $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1",
+ intval($parid)
+ );
+ }
+ }
+
+ if(($r === false) || (! count($r))) {
+ notice( t('Unable to locate original post.') . EOL);
+ if(x($_REQUEST,'return'))
+ goaway(z_root() . "/" . $return_path );
+ killme();
+ }
+
+ // can_comment_on_post() needs info from the following xchan_query
+ xchan_query($r);
+
+ $parent_item = $r[0];
+ $parent = $r[0]['id'];
+
+ // multi-level threading - preserve the info but re-parent to our single level threading
+
+ $thr_parent = $parent_mid;
+
+ $route = $parent_item['route'];
+
+ }
+
+ if(! $observer)
+ $observer = \App::get_observer();
+
+ if($parent) {
+ logger('mod_item: item_post parent=' . $parent);
+ $can_comment = false;
+ if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self']))
+ $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments');
+ else
+ $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item);
+
+ if(! $can_comment) {
+ notice( t('Permission denied.') . EOL) ;
+ if(x($_REQUEST,'return'))
+ goaway(z_root() . "/" . $return_path );
+ killme();
+ }
+ }
+ else {
+ if(! perm_is_allowed($profile_uid,$observer['xchan_hash'],($webpage) ? 'write_pages' : 'post_wall')) {
+ notice( t('Permission denied.') . EOL) ;
+ if(x($_REQUEST,'return'))
+ goaway(z_root() . "/" . $return_path );
+ killme();
+ }
+ }
+
+
+ // is this an edited post?
+
+ $orig_post = null;
+
+ if($namespace && $remote_id) {
+ // It wasn't an internally generated post - see if we've got an item matching this remote service id
+ $i = q("select iid from item_id where service = '%s' and sid = '%s' limit 1",
+ dbesc($namespace),
+ dbesc($remote_id)
+ );
+ if($i)
+ $post_id = $i[0]['iid'];
+ }
+
+ $iconfig = null;
+
+ if($post_id) {
+ $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1",
+ intval($profile_uid),
+ intval($post_id)
+ );
+ if(! count($i))
+ killme();
+ $orig_post = $i[0];
+ $iconfig = q("select * from iconfig where iid = %d",
+ intval($post_id)
+ );
+ }
+
+
+ if(! $channel) {
+ if($uid && $uid == $profile_uid) {
+ $channel = \App::get_channel();
+ }
+ else {
+ // posting as yourself but not necessarily to a channel you control
+ $r = q("select * from channel left join account on channel_account_id = account_id where channel_id = %d LIMIT 1",
+ intval($profile_uid)
+ );
+ if($r)
+ $channel = $r[0];
+ }
+ }
+
+
+ if(! $channel) {
+ logger("mod_item: no channel.");
+ if(x($_REQUEST,'return'))
+ goaway(z_root() . "/" . $return_path );
+ killme();
+ }
+
+ $owner_xchan = null;
+
+ $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ dbesc($channel['channel_hash'])
+ );
+ if($r && count($r)) {
+ $owner_xchan = $r[0];
+ }
+ else {
+ logger("mod_item: no owner.");
+ if(x($_REQUEST,'return'))
+ goaway(z_root() . "/" . $return_path );
+ killme();
+ }
+
+ $walltowall = false;
+ $walltowall_comment = false;
+
+ if($remote_xchan)
+ $observer = $remote_observer;
+
+ if($observer) {
+ logger('mod_item: post accepted from ' . $observer['xchan_name'] . ' for ' . $owner_xchan['xchan_name'], LOGGER_DEBUG);
+
+ // wall-to-wall detection.
+ // For top-level posts, if the author and owner are different it's a wall-to-wall
+ // For comments, We need to additionally look at the parent and see if it's a wall post that originated locally.
+
+ if($observer['xchan_name'] != $owner_xchan['xchan_name']) {
+ if(($parent_item) && ($parent_item['item_wall'] && $parent_item['item_origin'])) {
+ $walltowall_comment = true;
+ $walltowall = true;
+ }
+ if(! $parent) {
+ $walltowall = true;
+ }
+ }
+ }
+
+ $acl = new \Zotlabs\Access\AccessList($channel);
+
+
+ $public_policy = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($channel['channel_r_stream'],true));
+ if($webpage)
+ $public_policy = '';
+ if($public_policy)
+ $private = 1;
+
+ if($orig_post) {
+ $private = 0;
+ // webpages are allowed to change ACLs after the fact. Normal conversation items aren't.
+ if($webpage) {
+ $acl->set_from_array($_REQUEST);
+ }
+ else {
+ $acl->set($orig_post);
+ $public_policy = $orig_post['public_policy'];
+ $private = $orig_post['item_private'];
+ }
+
+ if($private || $public_policy || $acl->is_private())
+ $private = 1;
+
+
+ $location = $orig_post['location'];
+ $coord = $orig_post['coord'];
+ $verb = $orig_post['verb'];
+ $app = $orig_post['app'];
+ $title = escape_tags(trim($_REQUEST['title']));
+ $body = trim($_REQUEST['body']);
+ $item_flags = $orig_post['item_flags'];
+
+ $item_origin = $orig_post['item_origin'];
+ $item_unseen = $orig_post['item_unseen'];
+ $item_starred = $orig_post['item_starred'];
+ $item_uplink = $orig_post['item_uplink'];
+ $item_consensus = $orig_post['item_consensus'];
+ $item_wall = $orig_post['item_wall'];
+ $item_thread_top = $orig_post['item_thread_top'];
+ $item_notshown = $orig_post['item_notshown'];
+ $item_nsfw = $orig_post['item_nsfw'];
+ $item_relay = $orig_post['item_relay'];
+ $item_mentionsme = $orig_post['item_mentionsme'];
+ $item_nocomment = $orig_post['item_nocomment'];
+ $item_obscured = $orig_post['item_obscured'];
+ $item_verified = $orig_post['item_verified'];
+ $item_retained = $orig_post['item_retained'];
+ $item_rss = $orig_post['item_rss'];
+ $item_deleted = $orig_post['item_deleted'];
+ $item_type = $orig_post['item_type'];
+ $item_hidden = $orig_post['item_hidden'];
+ $item_unpublished = $orig_post['item_unpublished'];
+ $item_delayed = $orig_post['item_delayed'];
+ $item_pending_remove = $orig_post['item_pending_remove'];
+ $item_blocked = $orig_post['item_blocked'];
+
+
+
+ $postopts = $orig_post['postopts'];
+ $created = $orig_post['created'];
+ $mid = $orig_post['mid'];
+ $parent_mid = $orig_post['parent_mid'];
+ $plink = $orig_post['plink'];
+
+ }
+ else {
+ if(! $walltowall) {
+ if((array_key_exists('contact_allow',$_REQUEST))
+ || (array_key_exists('group_allow',$_REQUEST))
+ || (array_key_exists('contact_deny',$_REQUEST))
+ || (array_key_exists('group_deny',$_REQUEST))) {
+ $acl->set_from_array($_REQUEST);
+ }
+ elseif(! $api_source) {
+
+ // if no ACL has been defined and we aren't using the API, the form
+ // didn't send us any parameters. This means there's no ACL or it has
+ // been reset to the default audience.
+ // If $api_source is set and there are no ACL parameters, we default
+ // to the channel permissions which were set in the ACL contructor.
+
+ $acl->set(array('allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''));
+ }
+ }
+
+
+ $location = notags(trim($_REQUEST['location']));
+ $coord = notags(trim($_REQUEST['coord']));
+ $verb = notags(trim($_REQUEST['verb']));
+ $title = escape_tags(trim($_REQUEST['title']));
+ $body = trim($_REQUEST['body']);
+ $body .= trim($_REQUEST['attachment']);
+ $postopts = '';
+
+ $private = intval($acl->is_private() || ($public_policy));
+
+ // If this is a comment, set the permissions from the parent.
+
+ if($parent_item) {
+ $private = 0;
+ $acl->set($parent_item);
+ $private = intval($acl->is_private() || $parent_item['item_private']);
+ $public_policy = $parent_item['public_policy'];
+ $owner_hash = $parent_item['owner_xchan'];
+ }
+
+ if(! strlen($body)) {
+ if($preview)
+ killme();
+ info( t('Empty post discarded.') . EOL );
+ if(x($_REQUEST,'return'))
+ goaway(z_root() . "/" . $return_path );
+ killme();
+ }
+ }
+
+
+ $expires = NULL_DATE;
+
+ if(feature_enabled($profile_uid,'content_expire')) {
+ if(x($_REQUEST,'expire')) {
+ $expires = datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expire']);
+ if($expires <= datetime_convert())
+ $expires = NULL_DATE;
+ }
+ }
+
+ $mimetype = notags(trim($_REQUEST['mimetype']));
+ if(! $mimetype)
+ $mimetype = 'text/bbcode';
+
+ if($preview) {
+ $body = z_input_filter($profile_uid,$body,$mimetype);
+ }
+
+
+ // Verify ability to use html or php!!!
+
+ $execflag = false;
+
+ if($mimetype !== 'text/bbcode') {
+ $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($profile_uid)
+ );
+ if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) {
+ if($uid && (get_account_id() == $z[0]['account_id'])) {
+ $execflag = true;
+ }
+ else {
+ notice( t('Executable content type not permitted to this channel.') . EOL);
+ if(x($_REQUEST,'return'))
+ goaway(z_root() . "/" . $return_path );
+ killme();
+ }
+ }
+ }
+
+ $gacl = $acl->get();
+ $str_contact_allow = $gacl['allow_cid'];
+ $str_group_allow = $gacl['allow_gid'];
+ $str_contact_deny = $gacl['deny_cid'];
+ $str_group_deny = $gacl['deny_gid'];
+
+ if($mimetype === 'text/bbcode') {
+
+ require_once('include/text.php');
+
+ // Markdown doesn't work correctly. Do not re-enable unless you're willing to fix it and support it.
+
+ // Sample that will probably give you grief - you must preserve the linebreaks
+ // and provide the correct markdown interpretation and you cannot allow unfiltered HTML
+
+ // Markdown
+ // ========
+ //
+ // **bold** abcde
+ // fghijkl
+ // *italic*
+ // <img src="javascript:alert('hacked');" />
+
+ // if($uid && $uid == $profile_uid && feature_enabled($uid,'markdown')) {
+ // require_once('include/bb2diaspora.php');
+ // $body = escape_tags(trim($body));
+ // $body = str_replace("\n",'<br />', $body);
+ // $body = preg_replace_callback('/\[share(.*?)\]/ism','\share_shield',$body);
+ // $body = diaspora2bb($body,true);
+ // $body = preg_replace_callback('/\[share(.*?)\]/ism','\share_unshield',$body);
+ // }
+
+ // BBCODE alert: the following functions assume bbcode input
+ // and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
+ // we may need virtual or template classes to implement the possible alternatives
+
+ // Work around doubled linefeeds in Tinymce 3.5b2
+ // First figure out if it's a status post that would've been
+ // created using tinymce. Otherwise leave it alone.
+
+ $plaintext = true;
+
+ // $plaintext = ((feature_enabled($profile_uid,'richtext')) ? false : true);
+ // if((! $parent) && (! $api_source) && (! $plaintext)) {
+ // $body = fix_mce_lf($body);
+ // }
+
+
+
+ // If we're sending a private top-level message with a single @-taggable channel as a recipient, @-tag it, if our pconfig is set.
+
+
+ if((! $parent) && (get_pconfig($profile_uid,'system','tagifonlyrecip')) && (substr_count($str_contact_allow,'<') == 1) && ($str_group_allow == '') && ($str_contact_deny == '') && ($str_group_deny == '')) {
+ $x = q("select abook_id, abook_their_perms from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+ dbesc(str_replace(array('<','>'),array('',''),$str_contact_allow)),
+ intval($profile_uid)
+ );
+ if($x && ($x[0]['abook_their_perms'] & PERMS_W_TAGWALL))
+ $body .= "\n\n@group+" . $x[0]['abook_id'] . "\n";
+ }
+
+ /**
+ * fix naked links by passing through a callback to see if this is a red site
+ * (already known to us) which will get a zrl, otherwise link with url, add bookmark tag to both.
+ * First protect any url inside certain bbcode tags so we don't double link it.
+ */
+
+
+ $body = preg_replace_callback('/\[code(.*?)\[\/(code)\]/ism','\red_escape_codeblock',$body);
+ $body = preg_replace_callback('/\[url(.*?)\[\/(url)\]/ism','\red_escape_codeblock',$body);
+ $body = preg_replace_callback('/\[zrl(.*?)\[\/(zrl)\]/ism','\red_escape_codeblock',$body);
+
+ $body = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,]+)/ism", '\red_zrl_callback', $body);
+
+ $body = preg_replace_callback('/\[\$b64zrl(.*?)\[\/(zrl)\]/ism','\red_unescape_codeblock',$body);
+ $body = preg_replace_callback('/\[\$b64url(.*?)\[\/(url)\]/ism','\red_unescape_codeblock',$body);
+ $body = preg_replace_callback('/\[\$b64code(.*?)\[\/(code)\]/ism','\red_unescape_codeblock',$body);
+
+
+ // fix any img tags that should be zmg
+
+ $body = preg_replace_callback('/\[img(.*?)\](.*?)\[\/img\]/ism','\red_zrlify_img_callback',$body);
+
+
+ $body = bb_translate_video($body);
+
+ /**
+ * Fold multi-line [code] sequences
+ */
+
+ $body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body);
+
+ $body = scale_external_images($body,false);
+
+
+ // Look for tags and linkify them
+ $results = linkify_tags($a, $body, ($uid) ? $uid : $profile_uid);
+
+ if($results) {
+
+ // Set permissions based on tag replacements
+ set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item, $private);
+
+ $post_tags = array();
+ foreach($results as $result) {
+ $success = $result['success'];
+ if($success['replaced']) {
+ $post_tags[] = array(
+ 'uid' => $profile_uid,
+ 'type' => $success['termtype'],
+ 'otype' => TERM_OBJ_POST,
+ 'term' => $success['term'],
+ 'url' => $success['url']
+ );
+ }
+ }
+ }
+
+
+ /**
+ *
+ * When a photo was uploaded into the message using the (profile wall) ajax
+ * uploader, The permissions are initially set to disallow anybody but the
+ * owner from seeing it. This is because the permissions may not yet have been
+ * set for the post. If it's private, the photo permissions should be set
+ * appropriately. But we didn't know the final permissions on the post until
+ * now. So now we'll look for links of uploaded photos and attachments that are in the
+ * post and set them to the same permissions as the post itself.
+ *
+ * If the post was end-to-end encrypted we can't find images and attachments in the body,
+ * use our media_str input instead which only contains these elements - but only do this
+ * when encrypted content exists because the photo/attachment may have been removed from
+ * the post and we should keep it private. If it's encrypted we have no way of knowing
+ * so we'll set the permissions regardless and realise that the media may not be
+ * referenced in the post.
+ *
+ * What is preventing us from being able to upload photos into comments is dealing with
+ * the photo and attachment permissions, since we don't always know who was in the
+ * distribution for the top level post.
+ *
+ * We might be able to provide this functionality with a lot of fiddling:
+ * - if the top level post is public (make the photo public)
+ * - if the top level post was written by us or a wall post that belongs to us (match the top level post)
+ * - if the top level post has privacy mentions, add those to the permissions.
+ * - otherwise disallow the photo *or* make the photo public. This is the part that gets messy.
+ */
+
+ if(! $preview) {
+ $this->fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
+
+ $this->fix_attached_file_permissions($channel,$observer['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
+
+ }
+
+
+ $attachments = '';
+ $match = false;
+
+ if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
+ $attachments = array();
+ $i = 0;
+ foreach($match[2] as $mtch) {
+ $attach_link = '';
+ $hash = substr($mtch,0,strpos($mtch,','));
+ $rev = intval(substr($mtch,strpos($mtch,',')));
+ $r = attach_by_hash_nodata($hash,$rev);
+ if($r['success']) {
+ $attachments[] = array(
+ 'href' => z_root() . '/attach/' . $r['data']['hash'],
+ 'length' => $r['data']['filesize'],
+ 'type' => $r['data']['filetype'],
+ 'title' => urlencode($r['data']['filename']),
+ 'revision' => $r['data']['revision']
+ );
+ }
+ $ext = substr($r['data']['filename'],strrpos($r['data']['filename'],'.'));
+ if(strpos($r['data']['filetype'],'audio/') !== false)
+ $attach_link = '[audio]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . (($ext) ? $ext : '') . '[/audio]';
+ elseif(strpos($r['data']['filetype'],'video/') !== false)
+ $attach_link = '[video]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . (($ext) ? $ext : '') . '[/video]';
+ $body = str_replace($match[1][$i],$attach_link,$body);
+ $i++;
+ }
+ }
+
+ }
+
+ // BBCODE end alert
+
+ 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' => $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
+ );
+ }
+ }
+
+ if($orig_post) {
+ // preserve original tags
+ $t = q("select * from term where oid = %d and otype = %d and uid = %d and type in ( %d, %d, %d )",
+ intval($orig_post['id']),
+ intval(TERM_OBJ_POST),
+ intval($profile_uid),
+ intval(TERM_UNKNOWN),
+ intval(TERM_FILE),
+ intval(TERM_COMMUNITYTAG)
+ );
+ if($t) {
+ foreach($t as $t1) {
+ $post_tags[] = array(
+ 'uid' => $profile_uid,
+ 'type' => $t1['type'],
+ 'otype' => TERM_OBJ_POST,
+ 'term' => $t1['term'],
+ 'url' => $t1['url'],
+ );
+ }
+ }
+ }
+
+
+ $item_unseen = ((local_channel() != $profile_uid) ? 1 : 0);
+ $item_wall = (($post_type === 'wall' || $post_type === 'wall-comment') ? 1 : 0);
+ $item_origin = (($origin) ? 1 : 0);
+ $item_consensus = (($consensus) ? 1 : 0);
+
+
+ // determine if this is a wall post
+
+ if($parent) {
+ $item_wall = $parent_item['item_wall'];
+ }
+ else {
+ if(! $webpage) {
+ $item_wall = 1;
+ }
+ }
+
+
+ if($moderated)
+ $item_blocked = ITEM_MODERATED;
+
+
+ if(! strlen($verb))
+ $verb = ACTIVITY_POST ;
+
+ $notify_type = (($parent) ? 'comment-new' : 'wall-new' );
+
+ if(! $mid) {
+ $mid = (($message_id) ? $message_id : item_message_id());
+ }
+ if(! $parent_mid) {
+ $parent_mid = $mid;
+ }
+
+ if($parent_item)
+ $parent_mid = $parent_item['mid'];
+
+ // Fallback so that we alway have a thr_parent
+
+ if(!$thr_parent)
+ $thr_parent = $mid;
+
+ $datarray = array();
+
+ $item_thread_top = ((! $parent) ? 1 : 0);
+
+ if ((! $plink) && ($item_thread_top)) {
+ $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $mid;
+ }
+
+
+
+
+
+ $datarray['aid'] = $channel['channel_account_id'];
+ $datarray['uid'] = $profile_uid;
+
+ $datarray['owner_xchan'] = (($owner_hash) ? $owner_hash : $owner_xchan['xchan_hash']);
+ $datarray['author_xchan'] = $observer['xchan_hash'];
+ $datarray['created'] = $created;
+ $datarray['edited'] = (($orig_post) ? datetime_convert() : $created);
+ $datarray['expires'] = $expires;
+ $datarray['commented'] = (($orig_post) ? datetime_convert() : $created);
+ $datarray['received'] = (($orig_post) ? datetime_convert() : $created);
+ $datarray['changed'] = (($orig_post) ? datetime_convert() : $created);
+ $datarray['mid'] = $mid;
+ $datarray['parent_mid'] = $parent_mid;
+ $datarray['mimetype'] = $mimetype;
+ $datarray['title'] = $title;
+ $datarray['body'] = $body;
+ $datarray['app'] = $app;
+ $datarray['location'] = $location;
+ $datarray['coord'] = $coord;
+ $datarray['verb'] = $verb;
+ $datarray['obj_type'] = $obj_type;
+ $datarray['allow_cid'] = $str_contact_allow;
+ $datarray['allow_gid'] = $str_group_allow;
+ $datarray['deny_cid'] = $str_contact_deny;
+ $datarray['deny_gid'] = $str_group_deny;
+ $datarray['item_private'] = $private;
+ $datarray['item_wall'] = $item_wall;
+ $datarray['attach'] = $attachments;
+ $datarray['thr_parent'] = $thr_parent;
+ $datarray['postopts'] = $postopts;
+ $datarray['item_unseen'] = $item_unseen;
+ $datarray['item_wall'] = $item_wall;
+ $datarray['item_origin'] = $item_origin;
+ $datarray['item_type'] = $webpage;
+ $datarray['item_thread_top'] = $item_thread_top;
+ $datarray['item_unseen'] = $item_unseen;
+ $datarray['item_starred'] = $item_starred;
+ $datarray['item_uplink'] = $item_uplink;
+ $datarray['item_consensus'] = $item_consensus;
+ $datarray['item_notshown'] = $item_notshown;
+ $datarray['item_nsfw'] = $item_nsfw;
+ $datarray['item_relay'] = $item_relay;
+ $datarray['item_mentionsme'] = $item_mentionsme;
+ $datarray['item_nocomment'] = $item_nocomment;
+ $datarray['item_obscured'] = $item_obscured;
+ $datarray['item_verified'] = $item_verified;
+ $datarray['item_retained'] = $item_retained;
+ $datarray['item_rss'] = $item_rss;
+ $datarray['item_deleted'] = $item_deleted;
+ $datarray['item_hidden'] = $item_hidden;
+ $datarray['item_unpublished'] = $item_unpublished;
+ $datarray['item_delayed'] = $item_delayed;
+ $datarray['item_pending_remove'] = $item_pending_remove;
+ $datarray['item_blocked'] = $item_blocked;
+
+ $datarray['layout_mid'] = $layout_mid;
+ $datarray['public_policy'] = $public_policy;
+ $datarray['comment_policy'] = map_scope($channel['channel_w_comment']);
+ $datarray['term'] = $post_tags;
+ $datarray['plink'] = $plink;
+ $datarray['route'] = $route;
+
+ if($iconfig)
+ $datarray['iconfig'] = $iconfig;
+
+ // preview mode - prepare the body for display and send it via json
+
+ if($preview) {
+ require_once('include/conversation.php');
+
+ $datarray['owner'] = $owner_xchan;
+ $datarray['author'] = $observer;
+ $datarray['attach'] = json_encode($datarray['attach']);
+ $o = conversation($a,array($datarray),'search',false,'preview');
+ // logger('preview: ' . $o, LOGGER_DEBUG);
+ echo json_encode(array('preview' => $o));
+ killme();
+ }
+ if($orig_post)
+ $datarray['edit'] = true;
+
+ if(feature_enabled($profile_uid,'suppress_duplicates') && (! $orig_post)) {
+
+ $z = q("select created from item where uid = %d and body = '%s'",
+ intval($profile_uid),
+ dbesc($body)
+ );
+
+ if($z) {
+ foreach($z as $zz) {
+ if($zz['created'] > datetime_convert('UTC','UTC', 'now - 2 minutes')) {
+ $datarray['cancel'] = 1;
+ notice( t('Duplicate post suppressed.') . EOL);
+ logger('Duplicate post. Faking plugin cancel.');
+ }
+ }
+ }
+ }
+
+ call_hooks('post_local',$datarray);
+
+ if(x($datarray,'cancel')) {
+ logger('mod_item: post cancelled by plugin or duplicate suppressed.');
+ if($return_path)
+ goaway(z_root() . "/" . $return_path);
+
+ $json = array('cancel' => 1);
+ $json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
+ echo json_encode($json);
+ killme();
+ }
+
+
+ if(mb_strlen($datarray['title']) > 255)
+ $datarray['title'] = mb_substr($datarray['title'],0,255);
+
+ if(array_key_exists('item_private',$datarray) && $datarray['item_private']) {
+
+ $datarray['body'] = trim(z_input_filter($datarray['uid'],$datarray['body'],$datarray['mimetype']));
+
+ if($uid) {
+ if($channel['channel_hash'] === $datarray['author_xchan']) {
+ $datarray['sig'] = base64url_encode(rsa_sign($datarray['body'],$channel['channel_prvkey']));
+ $datarray['item_verified'] = 1;
+ }
+ }
+ }
+
+ if($orig_post) {
+ $datarray['id'] = $post_id;
+
+ item_store_update($datarray,$execflag);
+
+ update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid);
+
+ if(! $parent) {
+ $r = q("select * from item where id = %d",
+ intval($post_id)
+ );
+ if($r) {
+ xchan_query($r);
+ $sync_item = fetch_post_tags($r);
+ $rid = q("select * from item_id where iid = %d",
+ intval($post_id)
+ );
+ build_sync_packet($uid,array('item' => array(encode_item($sync_item[0],true)),'item_id' => $rid));
+ }
+ }
+ if(! $nopush)
+ proc_run('php', "include/notifier.php", 'edit_post', $post_id);
+
+ if((x($_REQUEST,'return')) && strlen($return_path)) {
+ logger('return: ' . $return_path);
+ goaway(z_root() . "/" . $return_path );
+ }
+ killme();
+ }
+ else
+ $post_id = 0;
+
+ $post = item_store($datarray,$execflag);
+
+ $post_id = $post['item_id'];
+
+ if($post_id) {
+ logger('mod_item: saved item ' . $post_id);
+
+ if($parent) {
+
+ // only send comment notification if this is a wall-to-wall comment,
+ // otherwise it will happen during delivery
+
+ if(($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) {
+ notification(array(
+ 'type' => NOTIFY_COMMENT,
+ 'from_xchan' => $datarray['author_xchan'],
+ 'to_xchan' => $datarray['owner_xchan'],
+ 'item' => $datarray,
+ 'link' => z_root() . '/display/' . $datarray['mid'],
+ 'verb' => ACTIVITY_POST,
+ 'otype' => 'item',
+ 'parent' => $parent,
+ 'parent_mid' => $parent_item['mid']
+ ));
+
+ }
+ }
+ else {
+ $parent = $post_id;
+
+ if(($datarray['owner_xchan'] != $datarray['author_xchan']) && ($datarray['item_type'] == ITEM_TYPE_POST)) {
+ notification(array(
+ 'type' => NOTIFY_WALL,
+ 'from_xchan' => $datarray['author_xchan'],
+ 'to_xchan' => $datarray['owner_xchan'],
+ 'item' => $datarray,
+ 'link' => z_root() . '/display/' . $datarray['mid'],
+ 'verb' => ACTIVITY_POST,
+ 'otype' => 'item'
+ ));
+ }
+
+ if($uid && $uid == $profile_uid && (is_item_normal($datarray))) {
+ q("update channel set channel_lastpost = '%s' where channel_id = %d",
+ dbesc(datetime_convert()),
+ intval($uid)
+ );
+ }
+ }
+
+ // photo comments turn the corresponding item visible to the profile wall
+ // This way we don't see every picture in your new photo album posted to your wall at once.
+ // They will show up as people comment on them.
+
+ if(intval($parent_item['item_hidden'])) {
+ $r = q("UPDATE item SET item_hidden = 0 WHERE id = %d",
+ intval($parent_item['id'])
+ );
+ }
+ }
+ else {
+ logger('mod_item: unable to retrieve post that was just stored.');
+ notice( t('System error. Post not saved.') . EOL);
+ goaway(z_root() . "/" . $return_path );
+ // NOTREACHED
+ }
+
+
+ update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid);
+
+ if(($parent) && ($parent != $post_id)) {
+ // Store the comment signature information in case we need to relay to Diaspora
+ //$ditem = $datarray;
+ //$ditem['author'] = $observer;
+ //store_diaspora_comment_sig($ditem,$channel,$parent_item, $post_id, (($walltowall_comment) ? 1 : 0));
+ }
+ else {
+ $r = q("select * from item where id = %d",
+ intval($post_id)
+ );
+ if($r) {
+ xchan_query($r);
+ $sync_item = fetch_post_tags($r);
+ $rid = q("select * from item_id where iid = %d",
+ intval($post_id)
+ );
+ build_sync_packet($uid,array('item' => array(encode_item($sync_item[0],true)),'item_id' => $rid));
+ }
+ }
+
+ $datarray['id'] = $post_id;
+ $datarray['llink'] = z_root() . '/display/' . $channel['channel_address'] . '/' . $post_id;
+
+ call_hooks('post_local_end', $datarray);
+
+ if(! $nopush)
+ proc_run('php', 'include/notifier.php', $notify_type, $post_id);
+
+ logger('post_complete');
+
+
+
+
+
+
+ // figure out how to return, depending on from whence we came
+
+ if($api_source)
+ return $post;
+
+ if($return_path) {
+ goaway(z_root() . "/" . $return_path);
+ }
+
+ $json = array('success' => 1);
+ if(x($_REQUEST,'jsreload') && strlen($_REQUEST['jsreload']))
+ $json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
+
+ logger('post_json: ' . print_r($json,true), LOGGER_DEBUG);
+
+ echo json_encode($json);
+ killme();
+ // NOTREACHED
+ }
+
+
+ function get() {
+
+ if((! local_channel()) && (! remote_channel()))
+ return;
+
+ require_once('include/security.php');
+
+ if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
+
+ require_once('include/items.php');
+ $i = q("select id, uid, author_xchan, owner_xchan, source_xchan, item_type from item where id = %d limit 1",
+ intval(argv(2))
+ );
+
+ if($i) {
+ $can_delete = false;
+ $local_delete = false;
+ if(local_channel() && local_channel() == $i[0]['uid'])
+ $local_delete = true;
+
+ $sys = get_sys_channel();
+ if(is_site_admin() && $sys['channel_id'] == $i[0]['uid'])
+ $can_delete = true;
+
+ $ob_hash = get_observer_hash();
+ if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan']))
+ $can_delete = true;
+
+ if(! ($can_delete || $local_delete)) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ // if this is a different page type or it's just a local delete
+ // but not by the item author or owner, do a simple deletion
+
+ if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) {
+ drop_item($i[0]['id']);
+ }
+ else {
+ // complex deletion that needs to propagate and be performed in phases
+ drop_item($i[0]['id'],true,DROPITEM_PHASE1);
+ tag_deliver($i[0]['uid'],$i[0]['id']);
+ }
+ }
+ }
+ }
+
+
+ function fix_attached_photo_permissions($uid,$xchan_hash,$body,
+ $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny) {
+
+ if(get_pconfig($uid,'system','force_public_uploads')) {
+ $str_contact_allow = $str_group_allow = $str_contact_deny = $str_group_deny = '';
+ }
+
+ $match = null;
+ // match img and zmg image links
+ if(preg_match_all("/\[[zi]mg(.*?)\](.*?)\[\/[zi]mg\]/",$body,$match)) {
+ $images = $match[2];
+ if($images) {
+ foreach($images as $image) {
+ if(! stristr($image,z_root() . '/photo/'))
+ continue;
+ $image_uri = substr($image,strrpos($image,'/') + 1);
+ if(strpos($image_uri,'-') !== false)
+ $image_uri = substr($image_uri,0, strpos($image_uri,'-'));
+ if(strpos($image_uri,'.') !== false)
+ $image_uri = substr($image_uri,0, strpos($image_uri,'.'));
+ if(! strlen($image_uri))
+ continue;
+ $srch = '<' . $xchan_hash . '>';
+
+ $r = q("select folder from attach where hash = '%s' and uid = %d limit 1",
+ dbesc($image_uri),
+ intval($uid)
+ );
+ if($r && $r[0]['folder']) {
+ $f = q("select * from attach where hash = '%s' and is_dir = 1 and uid = %d limit 1",
+ dbesc($r[0]['folder']),
+ intval($uid)
+ );
+ if(($f) && (($f[0]['allow_cid']) || ($f[0]['allow_gid']) || ($f[0]['deny_cid']) || ($f[0]['deny_gid']))) {
+ $str_contact_allow = $f[0]['allow_cid'];
+ $str_group_allow = $f[0]['allow_gid'];
+ $str_contact_deny = $f[0]['deny_cid'];
+ $str_group_deny = $f[0]['deny_gid'];
+ }
+ }
+
+ $r = q("SELECT id FROM photo
+ WHERE allow_cid = '%s' AND allow_gid = '' AND deny_cid = '' AND deny_gid = ''
+ AND resource_id = '%s' AND uid = %d LIMIT 1",
+ dbesc($srch),
+ dbesc($image_uri),
+ intval($uid)
+ );
+
+ if($r) {
+ $r = q("UPDATE photo SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s'
+ WHERE resource_id = '%s' AND uid = %d ",
+ dbesc($str_contact_allow),
+ dbesc($str_group_allow),
+ dbesc($str_contact_deny),
+ dbesc($str_group_deny),
+ dbesc($image_uri),
+ intval($uid)
+ );
+
+ // also update the linked item (which is probably invisible)
+
+ $r = q("select id from item
+ WHERE allow_cid = '%s' AND allow_gid = '' AND deny_cid = '' AND deny_gid = ''
+ AND resource_id = '%s' and resource_type = 'photo' AND uid = %d LIMIT 1",
+ dbesc($srch),
+ dbesc($image_uri),
+ intval($uid)
+ );
+ if($r) {
+ $private = (($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny) ? true : false);
+
+ $r = q("UPDATE item SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d
+ WHERE id = %d AND uid = %d",
+ dbesc($str_contact_allow),
+ dbesc($str_group_allow),
+ dbesc($str_contact_deny),
+ dbesc($str_group_deny),
+ intval($private),
+ intval($r[0]['id']),
+ intval($uid)
+ );
+ }
+ $r = q("select id from attach where hash = '%s' and uid = %d limit 1",
+ dbesc($image_uri),
+ intval($uid)
+ );
+ if($r) {
+ q("update attach SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s'
+ WHERE id = %d AND uid = %d",
+ dbesc($str_contact_allow),
+ dbesc($str_group_allow),
+ dbesc($str_contact_deny),
+ dbesc($str_group_deny),
+ intval($r[0]['id']),
+ intval($uid)
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ function fix_attached_file_permissions($channel,$observer_hash,$body,
+ $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny) {
+
+ if(get_pconfig($channel['channel_id'],'system','force_public_uploads')) {
+ $str_contact_allow = $str_group_allow = $str_contact_deny = $str_group_deny = '';
+ }
+
+ $match = false;
+
+ if(preg_match_all("/\[attachment\](.*?)\[\/attachment\]/",$body,$match)) {
+ $attaches = $match[1];
+ if($attaches) {
+ foreach($attaches as $attach) {
+ $hash = substr($attach,0,strpos($attach,','));
+ $rev = intval(substr($attach,strpos($attach,',')));
+ attach_store($channel,$observer_hash,$options = 'update', array(
+ 'hash' => $hash,
+ 'revision' => $rev,
+ 'allow_cid' => $str_contact_allow,
+ 'allow_gid' => $str_group_allow,
+ 'deny_cid' => $str_contact_deny,
+ 'deny_gid' => $str_group_deny
+ ));
+ }
+ }
+ }
+ }
+
+ function item_check_service_class($channel_id,$iswebpage) {
+ $ret = array('success' => false, 'message' => '');
+
+ if ($iswebpage) {
+ $r = q("select count(i.id) as total from item i
+ right join channel c on (i.author_xchan=c.channel_hash and i.uid=c.channel_id )
+ and i.parent=i.id and i.item_type = %d and i.item_deleted = 0 and i.uid= %d ",
+ intval(ITEM_TYPE_WEBPAGE),
+ intval($channel_id)
+ );
+ }
+ else {
+ $r = q("select count(id) as total from item where parent = id and item_wall = 1 and uid = %d " . item_normal(),
+ intval($channel_id)
+ );
+ }
+
+ if(! $r) {
+ $ret['message'] = t('Unable to obtain post information from database.');
+ return $ret;
+ }
+
+ if (!$iswebpage) {
+ $max = service_class_fetch($channel_id,'total_items');
+ if(! service_class_allows($channel_id,'total_items',$r[0]['total'])) {
+ $result['message'] .= upgrade_message() . sprintf( t('You have reached your limit of %1$.0f top level posts.'),$max);
+ return $result;
+ }
+ }
+ else {
+ $max = service_class_fetch($channel_id,'total_pages');
+ if(! service_class_allows($channel_id,'total_pages',$r[0]['total'])) {
+ $result['message'] .= upgrade_message() . sprintf( t('You have reached your limit of %1$.0f webpages.'),$max);
+ return $result;
+ }
+ }
+
+ $ret['success'] = true;
+ return $ret;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Lang.php b/Zotlabs/Module/Lang.php
new file mode 100644
index 000000000..69f10fe6d
--- /dev/null
+++ b/Zotlabs/Module/Lang.php
@@ -0,0 +1,12 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Lang extends \Zotlabs\Web\Controller {
+
+ function get() {
+ return lang_selector();
+ }
+
+
+}
diff --git a/Zotlabs/Module/Layouts.php b/Zotlabs/Module/Layouts.php
new file mode 100644
index 000000000..50cb401bc
--- /dev/null
+++ b/Zotlabs/Module/Layouts.php
@@ -0,0 +1,199 @@
+<?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'],
+ 'bang' => '',
+ 'showacl' => false,
+ 'visitor' => false,
+ 'nopreview' => 1,
+ '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;
+ }
+
+}
diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php
new file mode 100644
index 000000000..ac8791950
--- /dev/null
+++ b/Zotlabs/Module/Like.php
@@ -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();
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Linkinfo.php b/Zotlabs/Module/Linkinfo.php
new file mode 100644
index 000000000..ef34bb465
--- /dev/null
+++ b/Zotlabs/Module/Linkinfo.php
@@ -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;
+ }
+
+
+
+
+}
diff --git a/Zotlabs/Module/Lockview.php b/Zotlabs/Module/Lockview.php
new file mode 100644
index 000000000..0df0dd4da
--- /dev/null
+++ b/Zotlabs/Module/Lockview.php
@@ -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();
+
+
+ }
+
+}
diff --git a/Zotlabs/Module/Locs.php b/Zotlabs/Module/Locs.php
new file mode 100644
index 000000000..4b5d58df5
--- /dev/null
+++ b/Zotlabs/Module/Locs.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Login.php b/Zotlabs/Module/Login.php
new file mode 100644
index 000000000..ff75e5268
--- /dev/null
+++ b/Zotlabs/Module/Login.php
@@ -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);
+ }
+
+}
diff --git a/Zotlabs/Module/Lostpass.php b/Zotlabs/Module/Lostpass.php
new file mode 100644
index 000000000..eeddd0a13
--- /dev/null
+++ b/Zotlabs/Module/Lostpass.php
@@ -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;
+ }
+
+ }
+
+}
diff --git a/Zotlabs/Module/Magic.php b/Zotlabs/Module/Magic.php
new file mode 100644
index 000000000..63db4a317
--- /dev/null
+++ b/Zotlabs/Module/Magic.php
@@ -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);
+
+ }
+
+}
diff --git a/Zotlabs/Module/Mail.php b/Zotlabs/Module/Mail.php
new file mode 100644
index 000000000..35cb3b9bf
--- /dev/null
+++ b/Zotlabs/Module/Mail.php
@@ -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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Manage.php b/Zotlabs/Module/Manage.php
new file mode 100644
index 000000000..fee202263
--- /dev/null
+++ b/Zotlabs/Module/Manage.php
@@ -0,0 +1,181 @@
+<?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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Match.php b/Zotlabs/Module/Match.php
new file mode 100644
index 000000000..c422e4b3e
--- /dev/null
+++ b/Zotlabs/Module/Match.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Menu.php b/Zotlabs/Module/Menu.php
new file mode 100644
index 000000000..9ada63911
--- /dev/null
+++ b/Zotlabs/Module/Menu.php
@@ -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;
+ }
+ }
+
+ }
+
+}
diff --git a/Zotlabs/Module/Message.php b/Zotlabs/Module/Message.php
new file mode 100644
index 000000000..58a138899
--- /dev/null
+++ b/Zotlabs/Module/Message.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Mitem.php b/Zotlabs/Module/Mitem.php
new file mode 100644
index 000000000..b64b50c8e
--- /dev/null
+++ b/Zotlabs/Module/Mitem.php
@@ -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;
+ }
+ }
+ }
+
+}
diff --git a/Zotlabs/Module/Mood.php b/Zotlabs/Module/Mood.php
new file mode 100644
index 000000000..b1007fd06
--- /dev/null
+++ b/Zotlabs/Module/Mood.php
@@ -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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Msearch.php b/Zotlabs/Module/Msearch.php
new file mode 100644
index 000000000..e96f78e16
--- /dev/null
+++ b/Zotlabs/Module/Msearch.php
@@ -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();
+
+ }
+}
diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php
new file mode 100644
index 000000000..77353da05
--- /dev/null
+++ b/Zotlabs/Module/Network.php
@@ -0,0 +1,531 @@
+<?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');
+
+
+
+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, (($channel['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : '')),
+ '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;
+ }
+
+}
diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php
new file mode 100644
index 000000000..3dca1b0b4
--- /dev/null
+++ b/Zotlabs/Module/New_channel.php
@@ -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;
+
+ }
+
+
+}
diff --git a/Zotlabs/Module/Nojs.php b/Zotlabs/Module/Nojs.php
new file mode 100644
index 000000000..6fd6d8106
--- /dev/null
+++ b/Zotlabs/Module/Nojs.php
@@ -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);
+
+ }
+}
diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php
new file mode 100644
index 000000000..e530e6ff4
--- /dev/null
+++ b/Zotlabs/Module/Notes.php
@@ -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);
+
+ }
+
+}
diff --git a/Zotlabs/Module/Notifications.php b/Zotlabs/Module/Notifications.php
new file mode 100644
index 000000000..d51d2861c
--- /dev/null
+++ b/Zotlabs/Module/Notifications.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Notify.php b/Zotlabs/Module/Notify.php
new file mode 100644
index 000000000..227491145
--- /dev/null
+++ b/Zotlabs/Module/Notify.php
@@ -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;
+
+ }
+}
diff --git a/Zotlabs/Module/Oembed.php b/Zotlabs/Module/Oembed.php
new file mode 100644
index 000000000..b02182053
--- /dev/null
+++ b/Zotlabs/Module/Oembed.php
@@ -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();
+ }
+
+}
diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php
new file mode 100644
index 000000000..f36a452e8
--- /dev/null
+++ b/Zotlabs/Module/Oep.php
@@ -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($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;
+
+ }
+}
diff --git a/Zotlabs/Module/Oexchange.php b/Zotlabs/Module/Oexchange.php
new file mode 100644
index 000000000..24fc14821
--- /dev/null
+++ b/Zotlabs/Module/Oexchange.php
@@ -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();
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Online.php b/Zotlabs/Module/Online.php
new file mode 100644
index 000000000..39399db38
--- /dev/null
+++ b/Zotlabs/Module/Online.php
@@ -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);
+ }
+
+}
diff --git a/Zotlabs/Module/Openid.php b/Zotlabs/Module/Openid.php
new file mode 100644
index 000000000..7a6e4a81f
--- /dev/null
+++ b/Zotlabs/Module/Openid.php
@@ -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
+ }
+
+}
diff --git a/Zotlabs/Module/Opensearch.php b/Zotlabs/Module/Opensearch.php
new file mode 100644
index 000000000..8e76038c9
--- /dev/null
+++ b/Zotlabs/Module/Opensearch.php
@@ -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();
+
+ }
+
+}
diff --git a/Zotlabs/Module/Page.php b/Zotlabs/Module/Page.php
new file mode 100644
index 000000000..64b940b0f
--- /dev/null
+++ b/Zotlabs/Module/Page.php
@@ -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 (( 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 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) {
+ require_once('include/comanche.php');
+ comanche_parser(get_app(),$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) {
+ require_once('include/comanche.php');
+ comanche_parser(get_app(),$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;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Pconfig.php b/Zotlabs/Module/Pconfig.php
new file mode 100644
index 000000000..b6264bddc
--- /dev/null
+++ b/Zotlabs/Module/Pconfig.php
@@ -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'
+ );
+ }
+
+}
diff --git a/Zotlabs/Module/Pdledit.php b/Zotlabs/Module/Pdledit.php
new file mode 100644
index 000000000..accfb6fa1
--- /dev/null
+++ b/Zotlabs/Module/Pdledit.php
@@ -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;
+ }
+
+}
diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php
new file mode 100644
index 000000000..408688886
--- /dev/null
+++ b/Zotlabs/Module/Photo.php
@@ -0,0 +1,250 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/security.php');
+require_once('include/photo/photo_driver.php');
+
+
+class Photo extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $prvcachecontrol = false;
+
+ switch(argc()) {
+ case 4:
+ $person = argv(3);
+ $res = argv(2);
+ $type = argv(1);
+ break;
+ case 2:
+ $photo = argv(1);
+ break;
+ case 1:
+ default:
+ killme();
+ // NOTREACHED
+ }
+
+ $observer_xchan = get_observer_hash();
+
+ $default = get_default_profile_photo();
+
+ if(isset($type)) {
+
+ /**
+ * Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites.
+ *
+ */
+
+ if($type === 'profile') {
+ switch($res) {
+
+ case 'm':
+ $resolution = 5;
+ $default = get_default_profile_photo(80);
+ break;
+ case 's':
+ $resolution = 6;
+ $default = get_default_profile_photo(48);
+ break;
+ case 'l':
+ default:
+ $resolution = 4;
+ break;
+ }
+ }
+
+ $uid = $person;
+
+ $r = q("SELECT * FROM photo WHERE scale = %d AND uid = %d AND photo_usage = %d LIMIT 1",
+ intval($resolution),
+ intval($uid),
+ intval(PHOTO_PROFILE)
+ );
+ if(count($r)) {
+ $data = dbunescbin($r[0]['data']);
+ $mimetype = $r[0]['type'];
+ }
+ if(intval($r[0]['os_storage']))
+ $data = file_get_contents($data);
+ if(! isset($data)) {
+ $data = file_get_contents($default);
+ $mimetype = 'image/png';
+ }
+ }
+ else {
+
+ /**
+ * Other photos
+ */
+
+ /* Check for a cookie to indicate display pixel density, in order to detect high-resolution
+ displays. This procedure was derived from the "Retina Images" by Jeremey Worboys,
+ used in accordance with the Creative Commons Attribution 3.0 Unported License.
+ Project link: https://github.com/Retina-Images/Retina-Images
+ License link: http://creativecommons.org/licenses/by/3.0/
+ */
+ $cookie_value = false;
+ if (isset($_COOKIE['devicePixelRatio'])) {
+ $cookie_value = intval($_COOKIE['devicePixelRatio']);
+ }
+ else {
+ // Force revalidation of cache on next request
+ $cache_directive = 'no-cache';
+ $status = 'no cookie';
+ }
+
+ $resolution = 0;
+
+ if(strpos($photo,'.') !== false)
+ $photo = substr($photo,0,strpos($photo,'.'));
+
+ if(substr($photo,-2,1) == '-') {
+ $resolution = intval(substr($photo,-1,1));
+ $photo = substr($photo,0,-2);
+ // If viewing on a high-res screen, attempt to serve a higher resolution image:
+ if ($resolution == 2 && ($cookie_value > 1))
+ {
+ $resolution = 1;
+ }
+ }
+
+ // If using resolution 1, make sure it exists before proceeding:
+ if ($resolution == 1)
+ {
+ $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND scale = %d LIMIT 1",
+ dbesc($photo),
+ intval($resolution)
+ );
+ if (!($r))
+ $resolution = 2;
+ }
+
+ $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND scale = %d LIMIT 1",
+ dbesc($photo),
+ intval($resolution)
+ );
+ if($r) {
+
+ $allowed = (($r[0]['uid']) ? perm_is_allowed($r[0]['uid'],$observer_xchan,'view_storage') : true);
+
+ $sql_extra = permissions_sql($r[0]['uid']);
+
+ // Now we'll see if we can access the photo
+
+ $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND scale = %d $sql_extra LIMIT 1",
+ dbesc($photo),
+ intval($resolution)
+ );
+
+ if($r && $allowed) {
+ $data = dbunescbin($r[0]['data']);
+ $mimetype = $r[0]['type'];
+ if(intval($r[0]['os_storage']))
+ $data = file_get_contents($data);
+ }
+ else {
+
+ // Does the picture exist? It may be a remote person with no credentials,
+ // but who should otherwise be able to view it. Show a default image to let
+ // them know permissions was denied. It may be possible to view the image
+ // through an authenticated profile visit.
+ // There won't be many completely unauthorised people seeing this because
+ // they won't have the photo link, so there's a reasonable chance that the person
+ // might be able to obtain permission to view it.
+
+ $r = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `scale` = %d LIMIT 1",
+ dbesc($photo),
+ intval($resolution)
+ );
+
+ if($r) {
+ logger('mod_photo: forbidden. ' . \App::$query_string);
+ $observer = \App::get_observer();
+ logger('mod_photo: observer = ' . (($observer) ? $observer['xchan_addr'] : '(not authenticated)'));
+ $data = file_get_contents('images/nosign.png');
+ $mimetype = 'image/png';
+ $prvcachecontrol = true;
+ }
+ }
+ }
+ }
+
+ if(! isset($data)) {
+ if(isset($resolution)) {
+ switch($resolution) {
+
+ case 4:
+ $data = file_get_contents(get_default_profile_photo());
+ $mimetype = 'image/png';
+ break;
+ case 5:
+ $data = file_get_contents(get_default_profile_photo(80));
+ $mimetype = 'image/png';
+ break;
+ case 6:
+ $data = file_get_contents(get_default_profile_photo(48));
+ $mimetype = 'image/png';
+ break;
+ default:
+ killme();
+ // NOTREACHED
+ break;
+ }
+ }
+ }
+
+ if(isset($res) && intval($res) && $res < 500) {
+ $ph = photo_factory($data, $mimetype);
+ if($ph->is_valid()) {
+ $ph->scaleImageSquare($res);
+ $data = $ph->imageString();
+ $mimetype = $ph->getType();
+ }
+ }
+
+ // Writing in cachefile
+ if (isset($cachefile) && $cachefile != '')
+ file_put_contents($cachefile, $data);
+
+ if(function_exists('header_remove')) {
+ header_remove('Pragma');
+ header_remove('pragma');
+ }
+
+ header("Content-type: " . $mimetype);
+
+ if($prvcachecontrol) {
+
+ // it is a private photo that they have no permission to view.
+ // tell the browser not to cache it, in case they authenticate
+ // and subsequently have permission to see it
+
+ header("Cache-Control: no-store, no-cache, must-revalidate");
+
+ }
+ else {
+ // The photo cache default is 1 day to provide a privacy trade-off,
+ // as somebody reducing photo permissions on a photo that is already
+ // "in the wild" won't be able to stop the photo from being viewed
+ // for this amount amount of time once it is in the browser cache.
+ // The privacy expectations of your site members and their perception
+ // of privacy where it affects the entire project may be affected.
+ // This has performance considerations but we highly recommend you
+ // leave it alone.
+
+ $cache = get_config('system','photo_cache_time');
+ if(! $cache)
+ $cache = (3600 * 24); // 1 day
+
+ header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT");
+ header("Cache-Control: max-age=" . $cache);
+
+ }
+ echo $data;
+ killme();
+ // NOTREACHED
+ }
+
+}
diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php
new file mode 100644
index 000000000..00a577847
--- /dev/null
+++ b/Zotlabs/Module/Photos.php
@@ -0,0 +1,1384 @@
+<?php
+namespace Zotlabs\Module;
+require_once('include/photo/photo_driver.php');
+require_once('include/photos.php');
+require_once('include/items.php');
+require_once('include/acl_selectors.php');
+require_once('include/bbcode.php');
+require_once('include/security.php');
+require_once('include/Contact.php');
+require_once('include/attach.php');
+require_once('include/text.php');
+
+
+
+class Photos 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 ispublic = '" . t('everybody') . "'; var profile_uid = " . ((\App::$data['channel']) ? \App::$data['channel']['channel_id'] : 0) . "; </script>" ;
+
+ }
+
+ return;
+ }
+
+
+
+ function post() {
+
+ logger('mod-photos: photos_post: begin' , LOGGER_DEBUG);
+
+
+ logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA);
+ logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA);
+
+ $ph = photo_factory('');
+
+ $phototypes = $ph->supportedTypes();
+
+ $can_post = false;
+
+ $page_owner_uid = \App::$data['channel']['channel_id'];
+
+ if(perm_is_allowed($page_owner_uid,get_observer_hash(),'write_storage'))
+ $can_post = true;
+
+ if(! $can_post) {
+ notice( t('Permission denied.') . EOL );
+ if(is_ajax())
+ killme();
+ return;
+ }
+
+ $s = abook_self($page_owner_uid);
+
+ if(! $s) {
+ notice( t('Page owner information could not be retrieved.') . EOL);
+ logger('mod_photos: post: unable to locate contact record for page owner. uid=' . $page_owner_uid);
+ if(is_ajax())
+ killme();
+ return;
+ }
+
+ $owner_record = $s[0];
+
+ $acl = new \Zotlabs\Access\AccessList(\App::$data['channel']);
+
+ if((argc() > 3) && (argv(2) === 'album')) {
+
+ $album = hex2bin(argv(3));
+
+ if($album === t('Profile Photos')) {
+ // not allowed
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+ }
+
+ if(! photos_album_exists($page_owner_uid,$album)) {
+ notice( t('Album not found.') . EOL);
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+ }
+
+
+ /*
+ * RENAME photo album
+ */
+
+ $newalbum = notags(trim($_REQUEST['albumname']));
+ if($newalbum != $album) {
+
+ // @fixme - syncronise with DAV or disallow completely
+
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+ // $x = photos_album_rename($page_owner_uid,$album,$newalbum);
+ // if($x) {
+ // $newurl = str_replace(bin2hex($album),bin2hex($newalbum),$_SESSION['photo_return']);
+ // goaway(z_root() . '/' . $newurl);
+ // }
+ }
+
+ /*
+ * DELETE photo album and all its photos
+ */
+
+ if($_REQUEST['dropalbum'] == t('Delete Album')) {
+
+
+ // This is dangerous because we combined file storage and photos into one interface
+ // This function will remove all photos from any directory with the same name since
+ // we have not passed the path value.
+
+ // The correct solution would be to use a full pathname from your storage root for 'album'
+ // We also need to prevent/block removing the storage root folder.
+
+ $folder_hash = '';
+
+ $r = q("select * from attach where is_dir = 1 and uid = %d and filename = '%s'",
+ intval($page_owner_uid),
+ dbesc($album)
+ );
+ if(! $r) {
+ notice( t('Album not found.') . EOL);
+ return;
+ }
+ if(count($r) > 1) {
+ notice( t('Multiple storage folders exist with this album name, but within different directories. Please remove the desired folder or folders using the Files manager') . EOL);
+ return;
+ }
+ else {
+ $folder_hash = $r[0]['hash'];
+ }
+
+
+
+ $res = array();
+
+ // get the list of photos we are about to delete
+
+ if(remote_channel() && (! local_channel())) {
+ $str = photos_album_get_db_idstr($page_owner_uid,$album,remote_channel());
+ }
+ elseif(local_channel()) {
+ $str = photos_album_get_db_idstr(local_channel(),$album);
+ }
+ else {
+ $str = null;
+ }
+ if(! $str) {
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+ }
+
+ $r = q("select id from item where resource_id in ( $str ) and resource_type = 'photo' and uid = %d " . item_normal(),
+ intval($page_owner_uid)
+ );
+ if($r) {
+ foreach($r as $i) {
+ attach_delete($page_owner_uid, $i['resource_id'], 1 );
+ }
+ }
+
+ // remove the associated photos in case they weren't attached to an item
+
+ q("delete from photo where resource_id in ( $str ) and uid = %d",
+ intval($page_owner_uid)
+ );
+
+ // @FIXME do the same for the linked attach
+
+ if($folder_hash) {
+ attach_delete($page_owner_uid,$folder_hash, 1);
+
+ $sync = attach_export_data(\App::$data['channel'],$folder_hash, true);
+
+ if($sync)
+ build_sync_packet($page_owner_uid,array('file' => array($sync)));
+ }
+
+ }
+
+ goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
+ }
+
+ if((argc() > 2) && (x($_REQUEST,'delete')) && ($_REQUEST['delete'] === t('Delete Photo'))) {
+
+ // same as above but remove single photo
+
+ $ob_hash = get_observer_hash();
+ if(! $ob_hash)
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+ $r = q("SELECT `id`, `resource_id` FROM `photo` WHERE ( xchan = '%s' or `uid` = %d ) AND `resource_id` = '%s' LIMIT 1",
+ dbesc($ob_hash),
+ intval(local_channel()),
+ dbesc(\App::$argv[2])
+ );
+
+ if($r) {
+ attach_delete($page_owner_uid, $r[0]['resource_id'], 1 );
+ $sync = attach_export_data(\App::$data['channel'],$r[0]['resource_id'], true);
+
+ if($sync)
+ build_sync_packet($page_owner_uid,array('file' => array($sync)));
+ }
+
+ goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $_SESSION['album_return']);
+ }
+
+
+ if((\App::$argc > 2) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false)) || (x($_POST,'albname') !== false)) {
+
+
+ $desc = ((x($_POST,'desc')) ? notags(trim($_POST['desc'])) : '');
+ $rawtags = ((x($_POST,'newtag')) ? notags(trim($_POST['newtag'])) : '');
+ $item_id = ((x($_POST,'item_id')) ? intval($_POST['item_id']) : 0);
+ $albname = ((x($_POST,'albname')) ? notags(trim($_POST['albname'])) : '');
+ $is_nsfw = ((x($_POST,'adult')) ? intval($_POST['adult']) : 0);
+
+ $acl->set_from_array($_POST);
+ $perm = $acl->get();
+
+ $resource_id = argv(2);
+
+ if(! strlen($albname))
+ $albname = datetime_convert('UTC',date_default_timezone_get(),'now', 'Y');
+
+
+ if((x($_POST,'rotate') !== false) &&
+ ( (intval($_POST['rotate']) == 1) || (intval($_POST['rotate']) == 2) )) {
+ logger('rotate');
+
+ $r = q("select * from photo where `resource_id` = '%s' and uid = %d and scale = 0 limit 1",
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+ if(count($r)) {
+ $d = (($r[0]['os_storage']) ? @file_get_contents($r[0]['data']) : dbunescbin($r[0]['data']));
+ $ph = photo_factory($d, $r[0]['type']);
+ if($ph->is_valid()) {
+ $rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 );
+ $ph->rotate($rotate_deg);
+
+ $width = $ph->getWidth();
+ $height = $ph->getHeight();
+
+ if(intval($r[0]['os_storage'])) {
+ @file_put_contents($r[0]['data'],$ph->imageString());
+ $data = $r[0]['data'];
+ $fsize = @filesize($r[0]['data']);
+ q("update attach set filesize = %d where hash = '%s' and uid = %d limit 1",
+ intval($fsize),
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+ }
+ else {
+ $data = $ph->imageString();
+ $fsize = strlen($data);
+ }
+
+ $x = q("update photo set data = '%s', `size` = %d, height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 0",
+ dbescbin($data),
+ intval($fsize),
+ intval($height),
+ intval($width),
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+
+ if($width > 1024 || $height > 1024)
+ $ph->scaleImage(1024);
+
+ $width = $ph->getWidth();
+ $height = $ph->getHeight();
+
+ $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 1",
+ dbescbin($ph->imageString()),
+ intval($height),
+ intval($width),
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+
+
+ if($width > 640 || $height > 640)
+ $ph->scaleImage(640);
+
+ $width = $ph->getWidth();
+ $height = $ph->getHeight();
+
+ $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 2",
+ dbescbin($ph->imageString()),
+ intval($height),
+ intval($width),
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+
+
+ if($width > 320 || $height > 320)
+ $ph->scaleImage(320);
+
+ $width = $ph->getWidth();
+ $height = $ph->getHeight();
+
+ $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 3",
+ dbescbin($ph->imageString()),
+ intval($height),
+ intval($width),
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+ }
+ }
+ }
+
+ $p = q("SELECT type, is_nsfw, description, resource_id, scale, allow_cid, allow_gid, deny_cid, deny_gid FROM photo WHERE resource_id = '%s' AND uid = %d ORDER BY scale DESC",
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+ if($p) {
+ $ext = $phototypes[$p[0]['type']];
+
+ $r = q("UPDATE `photo` SET `description` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource_id` = '%s' AND `uid` = %d",
+ dbesc($desc),
+ dbesc($perm['allow_cid']),
+ dbesc($perm['allow_gid']),
+ dbesc($perm['deny_cid']),
+ dbesc($perm['deny_gid']),
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+ }
+
+ $item_private = (($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny) ? true : false);
+
+ $old_is_nsfw = $p[0]['is_nsfw'];
+ if($old_is_nsfw != $is_nsfw) {
+ $r = q("update photo set is_nsfw = %d where resource_id = '%s' and uid = %d",
+ intval($is_nsfw),
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+ }
+
+ /* Don't make the item visible if the only change was the album name */
+
+ $visibility = 0;
+ if($p[0]['description'] !== $desc || strlen($rawtags))
+ $visibility = 1;
+
+ if(! $item_id) {
+ $item_id = photos_create_item(\App::$data['channel'],get_observer_hash(),$p[0],$visibility);
+
+ }
+
+ if($item_id) {
+ $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+ intval($item_id),
+ intval($page_owner_uid)
+ );
+
+ if($r) {
+ $old_tag = $r[0]['tag'];
+ $old_inform = $r[0]['inform'];
+ }
+ }
+
+
+ // make sure the linked item has the same permissions as the photo regardless of any other changes
+ $x = q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d
+ where id = %d",
+ dbesc($perm['allow_cid']),
+ dbesc($perm['allow_gid']),
+ dbesc($perm['deny_cid']),
+ dbesc($perm['deny_gid']),
+ intval($acl->is_private()),
+ intval($item_id)
+ );
+
+ // make sure the attach has the same permissions as the photo regardless of any other changes
+ $x = q("update attach set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where hash = '%s' and uid = %d and is_photo = 1",
+ dbesc($perm['allow_cid']),
+ dbesc($perm['allow_gid']),
+ dbesc($perm['deny_cid']),
+ dbesc($perm['deny_gid']),
+ dbesc($resource_id),
+ intval($page_owner_uid)
+ );
+
+
+
+ if(strlen($rawtags)) {
+
+ $str_tags = '';
+ $inform = '';
+
+ // if the new tag doesn't have a namespace specifier (@foo or #foo) give it a mention
+
+ $x = substr($rawtags,0,1);
+ if($x !== '@' && $x !== '#')
+ $rawtags = '@' . $rawtags;
+
+ require_once('include/text.php');
+ $profile_uid = \App::$profile['profile_uid'];
+
+ $results = linkify_tags($a, $rawtags, (local_channel()) ? local_channel() : $profile_uid);
+
+ $success = $results['success'];
+ $post_tags = array();
+
+ foreach($results as $result) {
+ $success = $result['success'];
+ if($success['replaced']) {
+ $post_tags[] = array(
+ 'uid' => $profile_uid,
+ 'type' => $success['termtype'],
+ 'otype' => TERM_OBJ_POST,
+ 'term' => $success['term'],
+ 'url' => $success['url']
+ );
+ }
+ }
+
+ $r = q("select * from item where id = %d and uid = %d limit 1",
+ intval($item_id),
+ intval($page_owner_uid)
+ );
+
+ if($r) {
+ $r = fetch_post_tags($r,true);
+ $datarray = $r[0];
+ if($post_tags) {
+ if((! array_key_exists('term',$datarray)) || (! is_array($datarray['term'])))
+ $datarray['term'] = $post_tags;
+ else
+ $datarray['term'] = array_merge($datarray['term'],$post_tags);
+ }
+ item_store_update($datarray,$execflag);
+ }
+
+ }
+
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+ return; // NOTREACHED
+
+ $sync = attach_export_data(\App::$data['channel'],$resource_id);
+
+ if($sync)
+ build_sync_packet($page_owner_uid,array('file' => array($sync)));
+
+ }
+
+
+ /**
+ * default post action - upload a photo
+ */
+
+ $channel = \App::$data['channel'];
+ $observer = \App::$data['observer'];
+
+ $_REQUEST['source'] = 'photos';
+ require_once('include/attach.php');
+
+ if(! local_channel()) {
+ $_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']);
+ $_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']);
+ $_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']);
+ $_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']);
+ }
+
+ $r = attach_store($channel,get_observer_hash(), '', $_REQUEST);
+
+ if(! $r['success']) {
+ notice($r['message'] . EOL);
+ }
+
+ if($_REQUEST['newalbum'])
+ goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($_REQUEST['newalbum']));
+ else
+ goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex(datetime_convert('UTC',date_default_timezone_get(),'now', 'Y')));
+
+ }
+
+
+
+ function get() {
+
+ // URLs:
+ // photos/name
+ // photos/name/album/xxxxx (xxxxx is album name)
+ // photos/name/image/xxxxx
+
+
+ if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
+ notice( t('Public access denied.') . EOL);
+ return;
+ }
+
+ $unsafe = ((array_key_exists('unsafe',$_REQUEST) && $_REQUEST['unsafe']) ? 1 : 0);
+
+ require_once('include/bbcode.php');
+ require_once('include/security.php');
+ require_once('include/conversation.php');
+
+ if(! x(\App::$data,'channel')) {
+ notice( t('No photos selected') . EOL );
+ return;
+ }
+
+ $ph = photo_factory('');
+ $phototypes = $ph->supportedTypes();
+
+ $_SESSION['photo_return'] = \App::$cmd;
+
+ //
+ // Parse arguments
+ //
+
+ $can_comment = perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'post_comments');
+
+ if(argc() > 3) {
+ $datatype = argv(2);
+ $datum = argv(3);
+ } else {
+ if(argc() > 2) {
+ $datatype = argv(2);
+ $datum = '';
+ }
+ else
+ $datatype = 'summary';
+ }
+
+ if(argc() > 4)
+ $cmd = argv(4);
+ else
+ $cmd = 'view';
+
+ //
+ // Setup permissions structures
+ //
+
+ $can_post = false;
+ $visitor = 0;
+
+
+ $owner_uid = \App::$data['channel']['channel_id'];
+ $owner_aid = \App::$data['channel']['channel_account_id'];
+
+ $observer = \App::get_observer();
+
+ $can_post = perm_is_allowed($owner_uid,$observer['xchan_hash'],'write_storage');
+ $can_view = perm_is_allowed($owner_uid,$observer['xchan_hash'],'view_storage');
+
+ if(! $can_view) {
+ notice( t('Access to this item is restricted.') . EOL);
+ return;
+ }
+
+ $sql_extra = permissions_sql($owner_uid);
+
+ $o = "";
+
+ $o .= "<script> var profile_uid = " . \App::$profile['profile_uid']
+ . "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; </script>\r\n";
+
+ // tabs
+
+ $_is_owner = (local_channel() && (local_channel() == $owner_uid));
+ $o .= profile_tabs($a,$_is_owner, \App::$data['channel']['channel_address']);
+
+ /**
+ * Display upload form
+ */
+
+ if( $can_post) {
+
+ $uploader = '';
+
+ $ret = array('post_url' => z_root() . '/photos/' . \App::$data['channel']['channel_address'],
+ 'addon_text' => $uploader,
+ 'default_upload' => true);
+
+ call_hooks('photo_upload_form',$ret);
+
+ /* Show space usage */
+
+ $r = q("select sum(size) as total from photo where aid = %d and scale = 0 ",
+ intval(\App::$data['channel']['channel_account_id'])
+ );
+
+
+ $limit = service_class_fetch(\App::$data['channel']['channel_id'],'photo_upload_limit');
+ if($limit !== false) {
+ $usage_message = sprintf( t("%1$.2f MB of %2$.2f MB photo storage used."), $r[0]['total'] / 1024000, $limit / 1024000 );
+ }
+ else {
+ $usage_message = sprintf( t('%1$.2f MB photo storage used.'), $r[0]['total'] / 1024000 );
+ }
+
+ if($_is_owner) {
+ $channel = \App::get_channel();
+
+ $acl = new \Zotlabs\Access\AccessList($channel);
+ $channel_acl = $acl->get();
+
+ $lockstate = (($acl->is_private()) ? 'lock' : 'unlock');
+ }
+
+ $aclselect = (($_is_owner) ? populate_acl($channel_acl,false) : '');
+
+ // this is wrong but is to work around an issue with js_upload wherein it chokes if these variables
+ // don't exist. They really should be set to a parseable representation of the channel's default permissions
+ // which can be processed by getSelected()
+
+ if(! $aclselect) {
+ $aclselect = '<input id="group_allow" type="hidden" name="allow_gid[]" value="" /><input id="contact_allow" type="hidden" name="allow_cid[]" value="" /><input id="group_deny" type="hidden" name="deny_gid[]" value="" /><input id="contact_deny" type="hidden" name="deny_cid[]" value="" />';
+ }
+
+ $selname = (($datum) ? hex2bin($datum) : '');
+
+ $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer']));
+
+ if(! $selname) {
+ $def_album = get_pconfig(\App::$data['channel']['channel_id'],'system','photo_path');
+ if($def_album) {
+ $selname = filepath_macro($def_album);
+ $albums['album'][] = array('text' => $selname);
+ }
+ }
+
+ $tpl = get_markup_template('photos_upload.tpl');
+ $upload_form = replace_macros($tpl,array(
+ '$pagename' => t('Upload Photos'),
+ '$sessid' => session_id(),
+ '$usage' => $usage_message,
+ '$nickname' => \App::$data['channel']['channel_address'],
+ '$newalbum_label' => t('Enter an album name'),
+ '$newalbum_placeholder' => t('or select an existing album (doubleclick)'),
+ '$visible' => array('visible', t('Create a status post for this upload'), 0,'', array(t('No'), t('Yes')), 'onclick="showHideBodyTextarea();"'),
+ '$caption' => array('description', t('Caption (optional):')),
+ '$body' => array('body', t('Description (optional):'),'', 'Description will only appear in the status post'),
+ '$albums' => $albums['albums'],
+ '$selname' => $selname,
+ '$permissions' => t('Permissions'),
+ '$aclselect' => $aclselect,
+ '$lockstate' => $lockstate,
+ '$uploader' => $ret['addon_text'],
+ '$default' => (($ret['default_upload']) ? true : false),
+ '$uploadurl' => $ret['post_url'],
+ '$submit' => t('Submit')
+
+ ));
+
+ }
+
+ //
+ // dispatch request
+ //
+
+ /*
+ * Display a single photo album
+ */
+
+ if($datatype === 'album') {
+
+ if(strlen($datum)) {
+ if((strlen($datum) & 1) || (! ctype_xdigit($datum))) {
+ notice( t('Album name could not be decoded') . EOL);
+ logger('mod_photos: illegal album encoding: ' . $datum);
+ $datum = '';
+ }
+ }
+
+ $album = (($datum) ? hex2bin($datum) : '');
+
+
+ \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n";
+
+
+ $r = q("SELECT `resource_id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` = '%s'
+ AND `scale` <= 4 and photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY `resource_id`",
+ intval($owner_uid),
+ dbesc($album),
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_PROFILE),
+ intval($unsafe)
+ );
+ if(count($r)) {
+ \App::set_pager_total(count($r));
+ \App::set_pager_itemspage(60);
+ } else {
+ goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
+ }
+
+ if($_GET['order'] === 'posted')
+ $order = 'ASC';
+ else
+ $order = 'DESC';
+
+
+ $r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.scale, p.description, p.created FROM photo p INNER JOIN
+ (SELECT resource_id, max(scale) scale FROM photo WHERE uid = %d AND album = '%s' AND scale <= 4 AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id) ph
+ ON (p.resource_id = ph.resource_id AND p.scale = ph.scale)
+ ORDER BY created $order LIMIT %d OFFSET %d",
+ intval($owner_uid),
+ dbesc($album),
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_PROFILE),
+ intval($unsafe),
+ intval(\App::$pager['itemspage']),
+ intval(\App::$pager['start'])
+ );
+
+ //edit album name
+ $album_edit = null;
+ if(($album !== t('Profile Photos')) && ($album !== 'Profile Photos') && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) {
+ if($can_post) {
+ $album_e = $album;
+ $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer']));
+
+ // @fixme - syncronise actions with DAV
+
+ // $edit_tpl = get_markup_template('album_edit.tpl');
+ // $album_edit = replace_macros($edit_tpl,array(
+ // '$nametext' => t('Enter a new album name'),
+ // '$name_placeholder' => t('or select an existing one (doubleclick)'),
+ // '$nickname' => \App::$data['channel']['channel_address'],
+ // '$album' => $album_e,
+ // '$albums' => $albums['albums'],
+ // '$hexalbum' => bin2hex($album),
+ // '$submit' => t('Submit'),
+ // '$dropsubmit' => t('Delete Album')
+ // ));
+
+ }
+ }
+
+ if($_GET['order'] === 'posted')
+ $order = array(t('Show Newest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($album));
+ else
+ $order = array(t('Show Oldest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($album) . '?f=&order=posted');
+
+ $photos = array();
+ if(count($r)) {
+ $twist = 'rotright';
+ foreach($r as $rr) {
+
+ if($twist == 'rotright')
+ $twist = 'rotleft';
+ else
+ $twist = 'rotright';
+
+ $ext = $phototypes[$rr['type']];
+
+ $imgalt_e = $rr['filename'];
+ $desc_e = $rr['description'];
+
+ $imagelink = (z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id']
+ . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''));
+
+ $photos[] = array(
+ 'id' => $rr['id'],
+ 'twist' => ' ' . $twist . rand(2,4),
+ 'link' => $imagelink,
+ 'title' => t('View Photo'),
+ 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['scale'] . '.' .$ext,
+ 'alt' => $imgalt_e,
+ 'desc'=> $desc_e,
+ 'ext' => $ext,
+ 'hash'=> $rr['resource_id'],
+ 'unknown' => t('Unknown')
+ );
+ }
+ }
+
+ if($_REQUEST['aj']) {
+ if($photos) {
+ $o = replace_macros(get_markup_template('photosajax.tpl'),array(
+ '$photos' => $photos,
+ '$album_id' => bin2hex($album)
+ ));
+ }
+ 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>";
+ $tpl = get_markup_template('photo_album.tpl');
+ $o .= replace_macros($tpl, array(
+ '$photos' => $photos,
+ '$album' => $album,
+ '$album_id' => bin2hex($album),
+ '$album_edit' => array(t('Edit Album'), $album_edit),
+ '$can_post' => $can_post,
+ '$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/upload/' . bin2hex($album)),
+ '$order' => $order,
+ '$upload_form' => $upload_form,
+ '$usage' => $usage_message
+ ));
+
+ }
+
+ if((! $photos) && ($_REQUEST['aj'])) {
+ $o .= '<div id="content-complete"></div>';
+ echo $o;
+ killme();
+ }
+
+ // $o .= paginate($a);
+
+ return $o;
+
+ }
+
+ /**
+ * Display one photo
+ */
+
+ if($datatype === 'image') {
+
+ \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n";
+
+ // fetch image, item containing image, then comments
+
+ $ph = q("SELECT id,aid,uid,xchan,resource_id,created,edited,title,`description`,album,filename,`type`,height,width,`size`,scale,photo_usage,is_nsfw,allow_cid,allow_gid,deny_cid,deny_gid FROM `photo` WHERE `uid` = %d AND `resource_id` = '%s'
+ $sql_extra ORDER BY `scale` ASC ",
+ intval($owner_uid),
+ dbesc($datum)
+ );
+
+ if(! $ph) {
+
+ /* Check again - this time without specifying permissions */
+
+ $ph = q("SELECT id FROM photo WHERE uid = %d AND resource_id = '%s' LIMIT 1",
+ intval($owner_uid),
+ dbesc($datum)
+ );
+ if($ph)
+ notice( t('Permission denied. Access to this item may be restricted.') . EOL);
+ else
+ notice( t('Photo not available') . EOL );
+ return;
+ }
+
+
+
+ $prevlink = '';
+ $nextlink = '';
+
+ if($_GET['order'] === 'posted')
+ $order = 'ASC';
+ else
+ $order = 'DESC';
+
+
+ $prvnxt = q("SELECT `resource_id` FROM `photo` WHERE `album` = '%s' AND `uid` = %d AND `scale` = 0
+ $sql_extra ORDER BY `created` $order ",
+ dbesc($ph[0]['album']),
+ intval($owner_uid)
+ );
+
+ if(count($prvnxt)) {
+ for($z = 0; $z < count($prvnxt); $z++) {
+ if($prvnxt[$z]['resource_id'] == $ph[0]['resource_id']) {
+ $prv = $z - 1;
+ $nxt = $z + 1;
+ if($prv < 0)
+ $prv = count($prvnxt) - 1;
+ if($nxt >= count($prvnxt))
+ $nxt = 0;
+ break;
+ }
+ }
+
+ $prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
+ $nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
+ }
+
+
+ if(count($ph) == 1)
+ $hires = $lores = $ph[0];
+ if(count($ph) > 1) {
+ if($ph[1]['scale'] == 2) {
+ // original is 640 or less, we can display it directly
+ $hires = $lores = $ph[0];
+ }
+ else {
+ $hires = $ph[0];
+ $lores = $ph[1];
+ }
+ }
+
+ $album_link = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($ph[0]['album']);
+ $tools = Null;
+ $lock = Null;
+
+ if($can_post && ($ph[0]['uid'] == $owner_uid)) {
+ $tools = array(
+ 'profile'=>array(z_root() . '/profile_photo/use/'.$ph[0]['resource_id'], t('Use as profile photo')),
+ 'cover'=>array(z_root() . '/cover_photo/use/'.$ph[0]['resource_id'], t('Use as cover photo')),
+ );
+ }
+
+ // lockstate
+ $lockstate = ( ( (strlen($ph[0]['allow_cid']) || strlen($ph[0]['allow_gid'])
+ || strlen($ph[0]['deny_cid']) || strlen($ph[0]['deny_gid'])) )
+ ? array('lock', t('Private Photo'))
+ : array('unlock', Null));
+
+ \App::$page['htmlhead'] .= '<script>$(document).keydown(function(event) {' . "\n";
+ if($prevlink)
+ \App::$page['htmlhead'] .= 'if(event.ctrlKey && event.keyCode == 37) { event.preventDefault(); window.location.href = \'' . $prevlink . '\'; }' . "\n";
+ if($nextlink)
+ \App::$page['htmlhead'] .= 'if(event.ctrlKey && event.keyCode == 39) { event.preventDefault(); window.location.href = \'' . $nextlink . '\'; }' . "\n";
+ \App::$page['htmlhead'] .= '});</script>';
+
+ if($prevlink)
+ $prevlink = array($prevlink, t('Previous'));
+
+ $photo = array(
+ 'href' => z_root() . '/photo/' . $hires['resource_id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']],
+ 'title'=> t('View Full Size'),
+ 'src' => z_root() . '/photo/' . $lores['resource_id'] . '-' . $lores['scale'] . '.' . $phototypes[$lores['type']] . '?f=&_u=' . datetime_convert('','','','ymdhis')
+ );
+
+ if($nextlink)
+ $nextlink = array($nextlink, t('Next'));
+
+
+ // Do we have an item for this photo?
+
+ $linked_items = q("SELECT * FROM item WHERE resource_id = '%s' and resource_type = 'photo'
+ $sql_extra LIMIT 1",
+ dbesc($datum)
+ );
+
+ $map = null;
+
+ if($linked_items) {
+
+ xchan_query($linked_items);
+ $linked_items = fetch_post_tags($linked_items,true);
+
+ $link_item = $linked_items[0];
+ $item_normal = item_normal();
+
+ $r = q("select * from item where parent_mid = '%s'
+ $item_normal and uid = %d $sql_extra ",
+ dbesc($link_item['mid']),
+ intval($link_item['uid'])
+
+ );
+
+ if($r) {
+ xchan_query($r);
+ $r = fetch_post_tags($r,true);
+ $r = conv_sort($r,'commented');
+ }
+
+ $tags = array();
+ if($link_item['term']) {
+ $cnt = 0;
+ foreach($link_item['term'] as $t) {
+ $tags[$cnt] = array(0 => format_term_for_display($t));
+ if($can_post && ($ph[0]['uid'] == $owner_uid)) {
+ $tags[$cnt][1] = 'tagrm/drop/' . $link_item['id'] . '/' . bin2hex($t['term']); //?f=&item=' . $link_item['id'];
+ $tags[$cnt][2] = t('Remove');
+ }
+ $cnt ++;
+ }
+ }
+
+ if((local_channel()) && (local_channel() == $link_item['uid'])) {
+ q("UPDATE `item` SET item_unseen = 0 WHERE parent = %d and uid = %d and item_unseen = 1",
+ intval($link_item['parent']),
+ intval(local_channel())
+ );
+ }
+
+ if($link_item['coord']) {
+ $map = generate_map($link_item['coord']);
+ }
+ }
+
+ // logger('mod_photo: link_item' . print_r($link_item,true));
+
+ // FIXME - remove this when we move to conversation module
+
+ $r = $r[0]['children'];
+
+ $edit = null;
+ if($can_post) {
+ $album_e = $ph[0]['album'];
+ $caption_e = $ph[0]['description'];
+ $aclselect_e = (($_is_owner) ? populate_acl($ph[0]) : '');
+ $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer']));
+
+ $_SESSION['album_return'] = bin2hex($ph[0]['album']);
+
+ $edit = array(
+ 'edit' => t('Edit photo'),
+ 'id' => $link_item['id'],
+ 'rotatecw' => t('Rotate CW (right)'),
+ 'rotateccw' => t('Rotate CCW (left)'),
+ 'albums' => $albums['albums'],
+ 'album' => $album_e,
+ 'newalbum_label' => t('Enter a new album name'),
+ 'newalbum_placeholder' => t('or select an existing one (doubleclick)'),
+ 'nickname' => \App::$data['channel']['channel_address'],
+ 'resource_id' => $ph[0]['resource_id'],
+ 'capt_label' => t('Caption'),
+ 'caption' => $caption_e,
+ 'tag_label' => t('Add a Tag'),
+ 'permissions' => t('Permissions'),
+ 'aclselect' => $aclselect_e,
+ 'lockstate' => $lockstate[0],
+ 'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'),
+ 'item_id' => ((count($linked_items)) ? $link_item['id'] : 0),
+ 'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'),
+ 'adult' => array('adult',t('Flag as adult in album view'), intval($ph[0]['is_nsfw']),''),
+ 'submit' => t('Submit'),
+ 'delete' => t('Delete Photo')
+ );
+ }
+
+ if(count($linked_items)) {
+
+ $cmnt_tpl = get_markup_template('comment_item.tpl');
+ $tpl = get_markup_template('photo_item.tpl');
+ $return_url = \App::$cmd;
+
+ $like_tpl = get_markup_template('like_noshare.tpl');
+
+ $likebuttons = '';
+
+ if($can_post || $can_comment) {
+ $likebuttons = array(
+ 'id' => $link_item['id'],
+ 'likethis' => t("I like this \x28toggle\x29"),
+ 'nolike' => t("I don't like this \x28toggle\x29"),
+ 'share' => t('Share'),
+ 'wait' => t('Please wait')
+ );
+ }
+
+ $comments = '';
+ if(! count($r)) {
+ if($can_post || $can_comment) {
+ $commentbox = replace_macros($cmnt_tpl,array(
+ '$return_path' => '',
+ '$mode' => 'photos',
+ '$jsreload' => $return_url,
+ '$type' => 'wall-comment',
+ '$id' => $link_item['id'],
+ '$parent' => $link_item['id'],
+ '$profile_uid' => $owner_uid,
+ '$mylink' => $observer['xchan_url'],
+ '$mytitle' => t('This is you'),
+ '$myphoto' => $observer['xchan_photo_s'],
+ '$comment' => t('Comment'),
+ '$submit' => t('Submit'),
+ '$preview' => t('Preview'),
+ '$ww' => '',
+ '$feature_encrypt' => false
+ ));
+ }
+ }
+
+ $alike = array();
+ $dlike = array();
+
+ $like = '';
+ $dislike = '';
+
+ $conv_responses = array(
+ 'like' => array('title' => t('Likes','title')),'dislike' => array('title' => t('Dislikes','title')),
+ 'agree' => array('title' => t('Agree','title')),'disagree' => array('title' => t('Disagree','title')), 'abstain' => array('title' => t('Abstain','title')),
+ 'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title'))
+ );
+
+
+
+
+ if($r) {
+
+ foreach($r as $item) {
+ builtin_activity_puller($item, $conv_responses);
+ }
+
+
+ $like_count = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid']] : '');
+ $like_list = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid'] . '-l'] : '');
+ if (count($like_list) > MAX_LIKERS) {
+ $like_list_part = array_slice($like_list, 0, MAX_LIKERS);
+ array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
+ } else {
+ $like_list_part = '';
+ }
+ $like_button_label = tt('Like','Likes',$like_count,'noun');
+
+ //if (feature_enabled($conv->get_profile_owner(),'dislike')) {
+ $dislike_count = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid']] : '');
+ $dislike_list = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid'] . '-l'] : '');
+ $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
+ if (count($dislike_list) > MAX_LIKERS) {
+ $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
+ array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
+ } else {
+ $dislike_list_part = '';
+ }
+ //}
+
+
+ $like = ((isset($alike[$link_item['mid']])) ? format_like($alike[$link_item['mid']],$alike[$link_item['mid'] . '-l'],'like',$link_item['mid']) : '');
+ $dislike = ((isset($dlike[$link_item['mid']])) ? format_like($dlike[$link_item['mid']],$dlike[$link_item['mid'] . '-l'],'dislike',$link_item['mid']) : '');
+
+ // display comments
+
+ foreach($r as $item) {
+ $comment = '';
+ $template = $tpl;
+ $sparkle = '';
+
+ if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent']))
+ continue;
+
+ $redirect_url = z_root() . '/redir/' . $item['cid'] ;
+
+
+ $profile_url = zid($item['author']['xchan_url']);
+ $sparkle = '';
+
+
+ $profile_name = $item['author']['xchan_name'];
+ $profile_avatar = $item['author']['xchan_photo_m'];
+
+ $profile_link = $profile_url;
+
+ $drop = '';
+
+ if($observer['xchan_hash'] === $item['author_xchan'] || $observer['xchan_hash'] === $item['owner_xchan'])
+ $drop = replace_macros(get_markup_template('photo_drop.tpl'), array('$id' => $item['id'], '$delete' => t('Delete')));
+
+
+ $name_e = $profile_name;
+ $title_e = $item['title'];
+ unobscure($item);
+ $body_e = prepare_text($item['body'],$item['mimetype']);
+
+ $comments .= replace_macros($template,array(
+ '$id' => $item['id'],
+ '$mode' => 'photos',
+ '$profile_url' => $profile_link,
+ '$name' => $name_e,
+ '$thumb' => $profile_avatar,
+ '$sparkle' => $sparkle,
+ '$title' => $title_e,
+ '$body' => $body_e,
+ '$ago' => relative_date($item['created']),
+ '$indent' => (($item['parent'] != $item['id']) ? ' comment' : ''),
+ '$drop' => $drop,
+ '$comment' => $comment
+ ));
+
+ }
+
+ if($can_post || $can_comment) {
+ $commentbox = replace_macros($cmnt_tpl,array(
+ '$return_path' => '',
+ '$jsreload' => $return_url,
+ '$type' => 'wall-comment',
+ '$id' => $link_item['id'],
+ '$parent' => $link_item['id'],
+ '$profile_uid' => $owner_uid,
+ '$mylink' => $observer['xchan_url'],
+ '$mytitle' => t('This is you'),
+ '$myphoto' => $observer['xchan_photo_s'],
+ '$comment' => t('Comment'),
+ '$submit' => t('Submit'),
+ '$ww' => ''
+ ));
+ }
+
+ }
+ $paginate = paginate($a);
+ }
+
+ $album_e = array($album_link,$ph[0]['album']);
+ $like_e = $like;
+ $dislike_e = $dislike;
+
+
+ $response_verbs = array('like');
+ if(feature_enabled($owner_uid,'dislike'))
+ $response_verbs[] = 'dislike';
+
+
+ $responses = get_responses($conv_responses,$response_verbs,'',$link_item);
+
+ $photo_tpl = get_markup_template('photo_view.tpl');
+ $o .= replace_macros($photo_tpl, array(
+ '$id' => $ph[0]['id'],
+ '$album' => $album_e,
+ '$tools' => $tools,
+ '$lock' => $lockstate[1],
+ '$photo' => $photo,
+ '$prevlink' => $prevlink,
+ '$nextlink' => $nextlink,
+ '$desc' => $ph[0]['description'],
+ '$filename' => $ph[0]['filename'],
+ '$unknown' => t('Unknown'),
+ '$tag_hdr' => t('In This Photo:'),
+ '$tags' => $tags,
+ 'responses' => $responses,
+ '$edit' => $edit,
+ '$map' => $map,
+ '$map_text' => t('Map'),
+ '$likebuttons' => $likebuttons,
+ '$like' => $like_e,
+ '$dislike' => $dislike_e,
+ '$like_count' => $like_count,
+ '$like_list' => $like_list,
+ '$like_list_part' => $like_list_part,
+ '$like_button_label' => $like_button_label,
+ '$like_modal_title' => t('Likes','noun'),
+ '$dislike_modal_title' => t('Dislikes','noun'),
+ '$dislike_count' => $dislike_count, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
+ '$dislike_list' => $dislike_list, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
+ '$dislike_list_part' => $dislike_list_part, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
+ '$dislike_button_label' => $dislike_button_label, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
+ '$modal_dismiss' => t('Close'),
+ '$comments' => $comments,
+ '$commentbox' => $commentbox,
+ '$paginate' => $paginate,
+ ));
+
+ \App::$data['photo_html'] = $o;
+
+ return $o;
+ }
+
+ // Default - show recent photos with upload link (if applicable)
+ //$o = '';
+
+ \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n";
+
+
+ $r = q("SELECT `resource_id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s'
+ and photo_usage in ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY `resource_id`",
+ intval(\App::$data['channel']['channel_id']),
+ dbesc('Contact Photos'),
+ dbesc( t('Contact Photos')),
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_PROFILE),
+ intval($unsafe)
+ );
+ if(count($r)) {
+ \App::set_pager_total(count($r));
+ \App::set_pager_itemspage(60);
+ }
+
+ $r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.album, p.scale, p.created FROM photo p INNER JOIN
+ (SELECT resource_id, max(scale) scale FROM photo
+ WHERE uid=%d AND album != '%s' AND album != '%s'
+ AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra group by resource_id) ph
+ ON (p.resource_id = ph.resource_id and p.scale = ph.scale) ORDER by p.created DESC LIMIT %d OFFSET %d",
+ intval(\App::$data['channel']['channel_id']),
+ dbesc('Contact Photos'),
+ dbesc( t('Contact Photos')),
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_PROFILE),
+ intval($unsafe),
+ intval(\App::$pager['itemspage']),
+ intval(\App::$pager['start'])
+ );
+
+
+
+ $photos = array();
+ if(count($r)) {
+ $twist = 'rotright';
+ foreach($r as $rr) {
+ if($twist == 'rotright')
+ $twist = 'rotleft';
+ else
+ $twist = 'rotright';
+ $ext = $phototypes[$rr['type']];
+
+ if(\App::get_template_engine() === 'internal') {
+ $alt_e = template_escape($rr['filename']);
+ $name_e = template_escape($rr['album']);
+ }
+ else {
+ $alt_e = $rr['filename'];
+ $name_e = $rr['album'];
+ }
+
+ $photos[] = array(
+ 'id' => $rr['id'],
+ 'twist' => ' ' . $twist . rand(2,4),
+ 'link' => z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id'],
+ 'title' => t('View Photo'),
+ 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . ((($rr['scale']) == 6) ? 4 : $rr['scale']) . '.' . $ext,
+ 'alt' => $alt_e,
+ 'album' => array(
+ 'link' => z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($rr['album']),
+ 'name' => $name_e,
+ 'alt' => t('View Album'),
+ ),
+
+ );
+ }
+ }
+
+ if($_REQUEST['aj']) {
+ if($photos) {
+ $o = replace_macros(get_markup_template('photosajax.tpl'),array(
+ '$photos' => $photos,
+ '$album_id' => bin2hex(t('Recent Photos'))
+ ));
+ }
+ 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>";
+ $tpl = get_markup_template('photos_recent.tpl');
+ $o .= replace_macros($tpl, array(
+ '$title' => t('Recent Photos'),
+ '$album_id' => bin2hex(t('Recent Photos')),
+ '$can_post' => $can_post,
+ '$upload' => array(t('Upload'), z_root().'/photos/'.\App::$data['channel']['channel_address'].'/upload'),
+ '$photos' => $photos,
+ '$upload_form' => $upload_form,
+ '$usage' => $usage_message
+ ));
+
+ }
+
+ if((! $photos) && ($_REQUEST['aj'])) {
+ $o .= '<div id="content-complete"></div>';
+ echo $o;
+ killme();
+ }
+
+ // paginate($a);
+ return $o;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php
new file mode 100644
index 000000000..bea4a08b7
--- /dev/null
+++ b/Zotlabs/Module/Ping.php
@@ -0,0 +1,497 @@
+<?php
+namespace Zotlabs\Module;
+/**
+ * @file mod/ping.php
+ *
+ */
+
+require_once('include/bbcode.php');
+require_once('include/notify.php');
+
+/**
+ * @brief do several updates when pinged.
+ *
+ * This function does several tasks. Whenever called it checks for new messages,
+ * introductions, notifications, etc. and returns a json with the results.
+ *
+ * @param App &$a
+ * @result JSON
+ */
+
+
+class Ping extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $result = array();
+ $notifs = array();
+
+ $result['notify'] = 0;
+ $result['home'] = 0;
+ $result['network'] = 0;
+ $result['intros'] = 0;
+ $result['mail'] = 0;
+ $result['register'] = 0;
+ $result['events'] = 0;
+ $result['events_today'] = 0;
+ $result['birthdays'] = 0;
+ $result['birthdays_today'] = 0;
+ $result['all_events'] = 0;
+ $result['all_events_today'] = 0;
+ $result['notice'] = array();
+ $result['info'] = array();
+
+ $t0 = dba_timer();
+
+ header("content-type: application/json");
+
+ $vnotify = false;
+
+ $item_normal = item_normal();
+
+ if(local_channel()) {
+ $vnotify = get_pconfig(local_channel(),'system','vnotify');
+ $evdays = intval(get_pconfig(local_channel(),'system','evdays'));
+ $ob_hash = get_observer_hash();
+ }
+
+ // if unset show all visual notification types
+ if($vnotify === false)
+ $vnotify = (-1);
+ if($evdays < 1)
+ $evdays = 3;
+
+ /**
+ * If you have several windows open to this site and switch to a different channel
+ * in one of them, the others may get into a confused state showing you a page or options
+ * on that page which were only valid under the old identity. You session has changed.
+ * Therefore we send a notification of this fact back to the browser where it is picked up
+ * in javascript and which reloads the page it is on so that it is valid under the context
+ * of the now current channel.
+ */
+
+ $result['invalid'] = ((intval($_GET['uid'])) && (intval($_GET['uid']) != local_channel()) ? 1 : 0);
+
+ /**
+ * Send all system messages (alerts) to the browser.
+ * Some are marked as informational and some represent
+ * errors or serious notifications. These typically
+ * will popup on the current page (no matter what page it is)
+ */
+
+ if(x($_SESSION, 'sysmsg')){
+ foreach ($_SESSION['sysmsg'] as $m){
+ $result['notice'][] = array('message' => $m);
+ }
+ unset($_SESSION['sysmsg']);
+ }
+ if(x($_SESSION, 'sysmsg_info')){
+ foreach ($_SESSION['sysmsg_info'] as $m){
+ $result['info'][] = array('message' => $m);
+ }
+ unset($_SESSION['sysmsg_info']);
+ }
+ if(! ($vnotify & VNOTIFY_INFO))
+ $result['info'] = array();
+ if(! ($vnotify & VNOTIFY_ALERT))
+ $result['notice'] = array();
+
+
+ if(\App::$install) {
+ echo json_encode($result);
+ killme();
+ }
+
+ /**
+ * Update chat presence indication (if applicable)
+ */
+
+ if(get_observer_hash() && (! $result['invalid'])) {
+ $r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
+ dbesc(get_observer_hash()),
+ dbesc($_SERVER['REMOTE_ADDR'])
+ );
+ $basic_presence = false;
+ if($r) {
+ $basic_presence = true;
+ q("update chatpresence set cp_last = '%s' where cp_id = %d",
+ dbesc(datetime_convert()),
+ intval($r[0]['cp_id'])
+ );
+ }
+ if(! $basic_presence) {
+ q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
+ values( '%s', '%s', '%s', '%s' ) ",
+ dbesc(get_observer_hash()),
+ dbesc(datetime_convert()),
+ dbesc('online'),
+ dbesc($_SERVER['REMOTE_ADDR'])
+ );
+ }
+ }
+
+ /**
+ * Chatpresence continued... if somebody hasn't pinged recently, they've most likely left the page
+ * and shouldn't count as online anymore. We allow an expection for bots.
+ */
+
+ q("delete from chatpresence where cp_last < %s - INTERVAL %s and cp_client != 'auto' ",
+ db_utcnow(), db_quoteinterval('3 MINUTE')
+ );
+
+ if((! local_channel()) || ($result['invalid'])) {
+ echo json_encode($result);
+ killme();
+ }
+
+ /**
+ * Everything following is only permitted under the context of a locally authenticated site member.
+ */
+
+
+ /**
+ * Handle "mark all xyz notifications read" requests.
+ */
+
+ // mark all items read
+ if(x($_REQUEST, 'markRead') && local_channel()) {
+ switch($_REQUEST['markRead']) {
+ case 'network':
+ $r = q("update item set item_unseen = 0 where item_unseen = 1 and uid = %d",
+ intval(local_channel())
+ );
+ break;
+ case 'home':
+ $r = q("update item set item_unseen = 0 where item_unseen = 1 and item_wall = 1 and uid = %d",
+ intval(local_channel())
+ );
+ break;
+ case 'messages':
+ $r = q("update mail set mail_seen = 1 where mail_seen = 0 and channel_id = %d ",
+ intval(local_channel())
+ );
+ break;
+ case 'all_events':
+ $r = q("update event set `ignore` = 1 where `ignore` = 0 and uid = %d AND start < '%s' AND start > '%s' ",
+ intval(local_channel()),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
+ );
+ break;
+ case 'notify':
+ $r = q("update notify set seen = 1 where uid = %d",
+ intval(local_channel())
+ );
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(x($_REQUEST, 'markItemRead') && local_channel()) {
+ $r = q("update item set item_unseen = 0 where parent = %d and uid = %d",
+ intval($_REQUEST['markItemRead']),
+ intval(local_channel())
+ );
+ }
+
+
+
+ /**
+ * URL ping/something will return detail for "something", e.g. a json list with which to populate a notification
+ * dropdown menu.
+ */
+
+ if(argc() > 1 && argv(1) === 'notify') {
+ $t = q("select count(*) as total from notify where uid = %d and seen = 0",
+ intval(local_channel())
+ );
+ if($t && intval($t[0]['total']) > 49) {
+ $z = q("select * from notify where uid = %d
+ and seen = 0 order by date desc limit 50",
+ intval(local_channel())
+ );
+ }
+ else {
+ $z1 = q("select * from notify where uid = %d
+ and seen = 0 order by date desc limit 50",
+ intval(local_channel())
+ );
+ $z2 = q("select * from notify where uid = %d
+ and seen = 1 order by date desc limit %d",
+ intval(local_channel()),
+ intval(50 - intval($t[0]['total']))
+ );
+ $z = array_merge($z1,$z2);
+ }
+
+ if(count($z)) {
+ foreach($z as $zz) {
+ $notifs[] = array(
+ 'notify_link' => z_root() . '/notify/view/' . $zz['id'],
+ 'name' => $zz['name'],
+ 'url' => $zz['url'],
+ 'photo' => $zz['photo'],
+ 'when' => relative_date($zz['date']),
+ 'hclass' => (($zz['seen']) ? 'notify-seen' : 'notify-unseen'),
+ 'message' => strip_tags(bbcode($zz['msg']))
+ );
+ }
+ }
+
+ echo json_encode(array('notify' => $notifs));
+ killme();
+ }
+
+ if(argc() > 1 && argv(1) === 'messages') {
+ $channel = \App::get_channel();
+ $t = q("select mail.*, xchan.* from mail left join xchan on xchan_hash = from_xchan
+ where channel_id = %d and mail_seen = 0 and mail_deleted = 0
+ and from_xchan != '%s' order by created desc limit 50",
+ intval(local_channel()),
+ dbesc($channel['channel_hash'])
+ );
+
+ if($t) {
+ foreach($t as $zz) {
+ $notifs[] = array(
+ 'notify_link' => z_root() . '/mail/' . $zz['id'],
+ 'name' => $zz['xchan_name'],
+ 'url' => $zz['xchan_url'],
+ 'photo' => $zz['xchan_photo_s'],
+ 'when' => relative_date($zz['created']),
+ 'hclass' => (intval($zz['mail_seen']) ? 'notify-seen' : 'notify-unseen'),
+ 'message' => t('sent you a private message'),
+ );
+ }
+ }
+
+ echo json_encode(array('notify' => $notifs));
+ killme();
+ }
+
+ if(argc() > 1 && (argv(1) === 'network' || argv(1) === 'home')) {
+ $result = array();
+
+ $r = q("SELECT * FROM item
+ WHERE item_unseen = 1 and uid = %d $item_normal
+ and author_xchan != '%s' ORDER BY created DESC limit 300",
+ intval(local_channel()),
+ dbesc($ob_hash)
+ );
+
+ if($r) {
+ xchan_query($r);
+ foreach($r as $item) {
+ if((argv(1) === 'home') && (! intval($item['item_wall'])))
+ continue;
+ $result[] = format_notification($item);
+ }
+ }
+ // logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA);
+ echo json_encode(array('notify' => $result));
+ killme();
+ }
+
+ if(argc() > 1 && (argv(1) === 'intros')) {
+ $result = array();
+
+ $r = q("SELECT * FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ORDER BY abook_created DESC LIMIT 50",
+ intval(local_channel())
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+ $result[] = array(
+ 'notify_link' => z_root() . '/connections/ifpending',
+ 'name' => $rr['xchan_name'],
+ 'url' => $rr['xchan_url'],
+ 'photo' => $rr['xchan_photo_s'],
+ 'when' => relative_date($rr['abook_created']),
+ 'hclass' => ('notify-unseen'),
+ 'message' => t('added your channel')
+ );
+ }
+ }
+ logger('ping (intros): ' . print_r($result, true), LOGGER_DATA);
+ echo json_encode(array('notify' => $result));
+ killme();
+ }
+
+ if(argc() > 1 && (argv(1) === 'all_events')) {
+ $bd_format = t('g A l F d') ; // 8 AM Friday January 18
+
+ $result = array();
+
+ $r = q("SELECT * FROM event left join xchan on event_xchan = xchan_hash
+ WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0
+ and type in ( 'event', 'birthday' )
+ ORDER BY `start` DESC LIMIT 1000",
+ intval(local_channel()),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+ if($rr['adjust'])
+ $md = datetime_convert('UTC', date_default_timezone_get(), $rr['start'], 'Y/m');
+ else
+ $md = datetime_convert('UTC', 'UTC', $rr['start'], 'Y/m');
+
+ $strt = datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['start']);
+ $today = ((substr($strt, 0, 10) === datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d')) ? true : false);
+
+ $when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['start'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
+
+ $result[] = array(
+ 'notify_link' => z_root() . '/events', // FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $rr['event_hash'],
+ 'name' => $rr['xchan_name'],
+ 'url' => $rr['xchan_url'],
+ 'photo' => $rr['xchan_photo_s'],
+ 'when' => $when,
+ 'hclass' => ('notify-unseen'),
+ 'message' => t('posted an event')
+ );
+ }
+ }
+ logger('ping (all_events): ' . print_r($result, true), LOGGER_DATA);
+ echo json_encode(array('notify' => $result));
+ killme();
+ }
+
+
+
+ /**
+ * Normal ping - just the counts, no detail
+ */
+
+ if($vnotify & VNOTIFY_SYSTEM) {
+ $t = q("select count(*) as total from notify where uid = %d and seen = 0",
+ intval(local_channel())
+ );
+ if($t)
+ $result['notify'] = intval($t[0]['total']);
+ }
+
+ $t1 = dba_timer();
+
+ if($vnotify & (VNOTIFY_NETWORK|VNOTIFY_CHANNEL)) {
+ $r = q("SELECT id, item_wall FROM item
+ WHERE item_unseen = 1 and uid = %d
+ $item_normal
+ and author_xchan != '%s'",
+ intval(local_channel()),
+ dbesc($ob_hash)
+ );
+
+ if($r) {
+ $arr = array('items' => $r);
+ call_hooks('network_ping', $arr);
+
+ foreach ($r as $it) {
+ if(intval($it['item_wall']))
+ $result['home'] ++;
+ else
+ $result['network'] ++;
+ }
+ }
+ }
+ if(! ($vnotify & VNOTIFY_NETWORK))
+ $result['network'] = 0;
+ if(! ($vnotify & VNOTIFY_CHANNEL))
+ $result['home'] = 0;
+
+
+ $t2 = dba_timer();
+
+ if($vnotify & VNOTIFY_INTRO) {
+ $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
+ intval(local_channel())
+ );
+
+ $t3 = dba_timer();
+
+ if($intr)
+ $result['intros'] = intval($intr[0]['total']);
+ }
+
+ $t4 = dba_timer();
+ $channel = \App::get_channel();
+
+ if($vnotify & VNOTIFY_MAIL) {
+ $mails = q("SELECT count(id) as total from mail
+ WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
+ intval(local_channel()),
+ dbesc($channel['channel_hash'])
+ );
+ if($mails)
+ $result['mail'] = intval($mails[0]['total']);
+ }
+
+ if($vnotify & VNOTIFY_REGISTER) {
+ if (\App::$config['system']['register_policy'] == REGISTER_APPROVE && is_site_admin()) {
+ $regs = q("SELECT count(account_id) as total from account where (account_flags & %d) > 0",
+ intval(ACCOUNT_PENDING)
+ );
+ if($regs)
+ $result['register'] = intval($regs[0]['total']);
+ }
+ }
+
+ $t5 = dba_timer();
+
+ if($vnotify & (VNOTIFY_EVENT|VNOTIFY_EVENTTODAY|VNOTIFY_BIRTHDAY)) {
+ $events = q("SELECT type, start, adjust FROM `event`
+ WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0
+ and type in ( 'event', 'birthday' )
+ ORDER BY `start` ASC ",
+ intval(local_channel()),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
+ );
+
+ if($events) {
+ $result['all_events'] = count($events);
+
+ if($result['all_events']) {
+ $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d');
+ foreach($events as $x) {
+ $bd = false;
+ if($x['type'] === 'birthday') {
+ $result['birthdays'] ++;
+ $bd = true;
+ }
+ else {
+ $result['events'] ++;
+ }
+ if(datetime_convert('UTC', ((intval($x['adjust'])) ? date_default_timezone_get() : 'UTC'), $x['start'], 'Y-m-d') === $str_now) {
+ $result['all_events_today'] ++;
+ if($bd)
+ $result['birthdays_today'] ++;
+ else
+ $result['events_today'] ++;
+ }
+ }
+ }
+ }
+ }
+ if(! ($vnotify & VNOTIFY_EVENT))
+ $result['all_events'] = $result['events'] = 0;
+ if(! ($vnotify & VNOTIFY_EVENTTODAY))
+ $result['all_events_today'] = $result['events_today'] = 0;
+ if(! ($vnotify & VNOTIFY_BIRTHDAY))
+ $result['birthdays'] = 0;
+
+
+ $x = json_encode($result);
+
+ $t6 = dba_timer();
+
+ // logger('ping timer: ' . sprintf('%01.4f %01.4f %01.4f %01.4f %01.4f %01.4f',$t6 - $t5, $t5 - $t4, $t4 - $t3, $t3 - $t2, $t2 - $t1, $t1 - $t0));
+
+ echo $x;
+ killme();
+ }
+
+}
diff --git a/Zotlabs/Module/Poco.php b/Zotlabs/Module/Poco.php
new file mode 100644
index 000000000..85c9348c0
--- /dev/null
+++ b/Zotlabs/Module/Poco.php
@@ -0,0 +1,13 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/socgraph.php');
+
+
+class Poco extends \Zotlabs\Web\Controller {
+
+ function init() {
+ poco($a,false);
+ }
+
+}
diff --git a/Zotlabs/Module/Poke.php b/Zotlabs/Module/Poke.php
new file mode 100644
index 000000000..123ecbc7b
--- /dev/null
+++ b/Zotlabs/Module/Poke.php
@@ -0,0 +1,194 @@
+<?php
+namespace Zotlabs\Module; /** @file */
+
+/**
+ *
+ * Poke, prod, finger, or otherwise do unspeakable things to somebody - who must be a connection in your address book
+ * This function can be invoked with the required arguments (verb and cid and private and possibly parent) silently via ajax or
+ * other web request. You must be logged in and connected to a channel.
+ * If the required arguments aren't present, we'll display a simple form to choose a recipient and a verb.
+ * parent is a special argument which let's you attach this activity as a comment to an existing conversation, which
+ * may have started with somebody else poking (etc.) somebody, but this isn't necessary. This can be used in the adult
+ * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
+ *
+ * private creates a private conversation with the recipient. Otherwise your channel's default post privacy is used.
+ *
+ */
+
+require_once('include/items.php');
+
+
+class Poke extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if(! local_channel())
+ return;
+
+ $uid = local_channel();
+ $channel = \App::get_channel();
+
+ $verb = notags(trim($_REQUEST['verb']));
+
+ if(! $verb)
+ return;
+
+ $verbs = get_poke_verbs();
+
+ if(! array_key_exists($verb,$verbs))
+ return;
+
+ $activity = ACTIVITY_POKE . '#' . urlencode($verbs[$verb][0]);
+
+ $contact_id = intval($_REQUEST['cid']);
+ if(! $contact_id)
+ return;
+
+ $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
+
+ logger('poke: verb ' . $verb . ' contact ' . $contact_id, LOGGER_DEBUG);
+
+
+ $r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where abook_id = %d and abook_channel = %d LIMIT 1",
+ intval($contact_id),
+ intval($uid)
+ );
+
+ if(! $r) {
+ logger('poke: no target ' . $contact_id);
+ return;
+ }
+
+ $target = $r[0];
+ $parent_item = null;
+
+ if($parent) {
+ $r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid
+ from item where id = %d and parent = %d and uid = %d limit 1",
+ intval($parent),
+ intval($parent),
+ intval($uid)
+ );
+ if($r) {
+ $parent_item = $r[0];
+ $parent_mid = $r[0]['mid'];
+ $item_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 {
+
+ $item_private = ((x($_GET,'private')) ? intval($_GET['private']) : 0);
+
+ $allow_cid = (($item_private) ? '<' . $target['abook_xchan']. '>' : $channel['channel_allow_cid']);
+ $allow_gid = (($item_private) ? '' : $channel['channel_allow_gid']);
+ $deny_cid = (($item_private) ? '' : $channel['channel_deny_cid']);
+ $deny_gid = (($item_private) ? '' : $channel['channel_deny_gid']);
+ }
+
+
+ $arr = array();
+
+ $arr['item_wall'] = 1;
+ $arr['owner_xchan'] = (($parent_item) ? $parent_item['owner_xchan'] : $channel['channel_hash']);
+ $arr['parent_mid'] = (($parent_mid) ? $parent_mid : $mid);
+ $arr['title'] = '';
+ $arr['allow_cid'] = $allow_cid;
+ $arr['allow_gid'] = $allow_gid;
+ $arr['deny_cid'] = $deny_cid;
+ $arr['deny_gid'] = $deny_gid;
+ $arr['verb'] = $activity;
+ $arr['item_private'] = $item_private;
+ $arr['obj_type'] = ACTIVITY_OBJ_PERSON;
+ $arr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t($verbs[$verb][0]) . ' ' . '[zrl=' . $target['xchan_url'] . ']' . $target['xchan_name'] . '[/zrl]';
+
+ $obj = array(
+ 'type' => ACTIVITY_OBJ_PERSON,
+ 'title' => $target['xchan_name'],
+ 'id' => $target['xchan_hash'],
+ 'link' => array(
+ array('rel' => 'alternate', 'type' => 'text/html', 'href' => $target['xchan_url']),
+ array('rel' => 'photo', 'type' => $target['xchan_photo_mimetype'], 'href' => $target['xchan_photo_l'])
+ ),
+ );
+
+ $arr['object'] = json_encode($obj);
+
+ $arr['item_origin'] = 1;
+ $arr['item_wall'] = 1;
+ $arr['item_unseen'] = 1;
+ if(! $parent_item)
+ $item['item_thread_top'] = 1;
+
+
+ post_activity_item($arr);
+
+ return;
+ }
+
+
+
+ function get() {
+
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ $name = '';
+ $id = '';
+
+ if(intval($_REQUEST['c'])) {
+ $r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash
+ where abook_id = %d and abook_channel = %d limit 1",
+ intval($_REQUEST['c']),
+ intval(local_channel())
+ );
+ if($r) {
+ $name = $r[0]['xchan_name'];
+ $id = $r[0]['abook_id'];
+ }
+ }
+
+ $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : '0');
+
+ $verbs = get_poke_verbs();
+
+ $shortlist = array();
+ foreach($verbs as $k => $v)
+ if($v[1] !== 'NOTRANSLATION')
+ $shortlist[] = array($k,$v[1]);
+
+
+ $poke_basic = get_config('system','poke_basic');
+ if($poke_basic) {
+ $title = t('Poke');
+ $desc = t('Poke somebody');
+ }
+ else {
+ $title = t('Poke/Prod');
+ $desc = t('Poke, prod or do other things to somebody');
+ }
+
+ $o = replace_macros(get_markup_template('poke_content.tpl'),array(
+ '$title' => $title,
+ '$poke_basic' => $poke_basic,
+ '$desc' => $desc,
+ '$clabel' => t('Recipient'),
+ '$choice' => t('Choose what you wish to do to recipient'),
+ '$verbs' => $shortlist,
+ '$parent' => $parent,
+ '$prv_desc' => t('Make this post private'),
+ '$private' => array('private', t('Make this post private'), false, ''),
+ '$submit' => t('Submit'),
+ '$name' => $name,
+ '$id' => $id
+ ));
+
+ return $o;
+
+ }
+}
diff --git a/Zotlabs/Module/Post.php b/Zotlabs/Module/Post.php
new file mode 100644
index 000000000..af231ab50
--- /dev/null
+++ b/Zotlabs/Module/Post.php
@@ -0,0 +1,36 @@
+<?php
+namespace Zotlabs\Module;
+
+/**
+ * @file mod/post.php
+ *
+ * @brief Zot endpoint.
+ *
+ */
+
+require_once('include/zot.php');
+
+
+class Post extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if (array_key_exists('auth', $_REQUEST)) {
+ $x = new \Zotlabs\Zot\Auth($_REQUEST);
+ exit;
+ }
+
+ }
+
+
+ function post() {
+
+ $z = new \Zotlabs\Zot\Receiver($_REQUEST['data'],get_config('system','prvkey'), new \Zotlabs\Zot\ZotHandler());
+
+ // notreached;
+
+ exit;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Prate.php b/Zotlabs/Module/Prate.php
new file mode 100644
index 000000000..65bbcca9a
--- /dev/null
+++ b/Zotlabs/Module/Prate.php
@@ -0,0 +1,105 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Prate extends \Zotlabs\Web\Controller {
+
+ function init() {
+ if($_SERVER['REQUEST_METHOD'] === 'post')
+ return;
+
+ if(! local_channel())
+ return;
+
+ $channel = \App::get_channel();
+
+ $target = argv(1);
+ if(! $target)
+ return;
+
+ $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
+ dbesc($channel['channel_hash']),
+ dbesc($target)
+ );
+ if($r)
+ json_return_and_die(array('rating' => $r[0]['xlink_rating'],'rating_text' => $r[0]['xlink_rating_text']));
+ killme();
+ }
+
+ function post() {
+
+ if(! local_channel())
+ return;
+
+ $channel = \App::get_channel();
+
+ $target = trim($_REQUEST['target']);
+ if(! $target)
+ return;
+
+ if($target === $channel['channel_hash'])
+ return;
+
+ $rating = intval($_POST['rating']);
+ if($rating < (-10))
+ $rating = (-10);
+ if($rating > 10)
+ $rating = 10;
+
+ $rating_text = trim(escape_tags($_REQUEST['rating_text']));
+
+ $signed = $target . '.' . $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($target)
+ );
+ 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($target),
+ 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);
+ }
+
+ json_return_and_die(array('result' => true));;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/Zotlabs/Module/Pretheme.php b/Zotlabs/Module/Pretheme.php
new file mode 100644
index 000000000..120fd5359
--- /dev/null
+++ b/Zotlabs/Module/Pretheme.php
@@ -0,0 +1,28 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Pretheme extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if($_REQUEST['theme']) {
+ $theme = $_REQUEST['theme'];
+ $info = get_theme_info($theme);
+ if($info) {
+ // unfortunately there will be no translation for this string
+ $desc = $info['description'];
+ $version = $info['version'];
+ $credits = $info['credits'];
+ }
+ else {
+ $desc = '';
+ $version = '';
+ $credits = '';
+ }
+ echo json_encode(array('img' => get_theme_screenshot($theme), 'desc' => $desc, 'version' => $version, 'credits' => $credits));
+ }
+ killme();
+ }
+
+}
diff --git a/Zotlabs/Module/Probe.php b/Zotlabs/Module/Probe.php
new file mode 100644
index 000000000..79abe9819
--- /dev/null
+++ b/Zotlabs/Module/Probe.php
@@ -0,0 +1,47 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/zot.php');
+
+
+class Probe extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ $o .= '<h3>Probe Diagnostic</h3>';
+
+ $o .= '<form action="probe" method="get">';
+ $o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
+ $o .= '<input type="submit" name="submit" value="Submit" /></form>';
+
+ $o .= '<br /><br />';
+
+ if(x($_GET,'addr')) {
+ $channel = \App::get_channel();
+ $addr = trim($_GET['addr']);
+ $do_import = ((intval($_GET['import']) && is_site_admin()) ? true : false);
+ $res = zot_finger($addr,$channel,false);
+ $o .= '<pre>';
+ if($res['success'])
+ $j = json_decode($res['body'],true);
+ else {
+ $o .= sprintf( t('Fetching URL returns error: %1$s'),$res['error'] . "\r\n\r\n");
+ $o .= "<strong>https connection failed. Trying again with auto failover to http.</strong>\r\n\r\n";
+ $res = zot_finger($addr,$channel,true);
+ if($res['success'])
+ $j = json_decode($res['body'],true);
+ else
+ $o .= sprintf( t('Fetching URL returns error: %1$s'),$res['error'] . "\r\n\r\n");
+
+ }
+ if($do_import && $j)
+ $x = import_xchan($j);
+ if($j && $j['permissions'] && $j['permissions']['iv'])
+ $j['permissions'] = json_decode(crypto_unencapsulate($j['permissions'],$channel['channel_prvkey']),true);
+ $o .= str_replace("\n",'<br />',print_r($j,true));
+ $o .= '</pre>';
+ }
+ return $o;
+ }
+
+}
diff --git a/Zotlabs/Module/Profile.php b/Zotlabs/Module/Profile.php
new file mode 100644
index 000000000..04a64fe76
--- /dev/null
+++ b/Zotlabs/Module/Profile.php
@@ -0,0 +1,90 @@
+<?php
+namespace Zotlabs\Module; /** @file */
+
+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');
+
+
+
+class Profile 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() {
+
+ if(get_config('system','block_public') && (! get_account_id()) && (! remote_channel())) {
+ return login();
+ }
+
+ $groups = array();
+
+ $tab = 'profile';
+ $o = '';
+
+ if(! (perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(), 'view_profile'))) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+
+ $is_owner = ((local_channel()) && (local_channel() == \App::$profile['profile_uid']) ? true : false);
+
+ if(\App::$profile['hidewall'] && (! $is_owner) && (! remote_channel())) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ $o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
+
+ \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";
+
+ $o .= advanced_profile($a);
+ call_hooks('profile_advanced',$o);
+ return $o;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php
new file mode 100644
index 000000000..8f879503c
--- /dev/null
+++ b/Zotlabs/Module/Profile_photo.php
@@ -0,0 +1,436 @@
+<?php
+namespace Zotlabs\Module;
+
+/* @file profile_photo.php
+ @brief Module-file with functions for handling of profile-photos
+
+*/
+
+
+require_once('include/photo/photo_driver.php');
+require_once('include/photos.php');
+require_once('include/identity.php');
+
+/* @brief Function for sync'ing permissions of profile-photos and their profile
+*
+* @param $profileid The id number of the profile to sync
+* @return void
+*/
+
+
+class Profile_photo extends \Zotlabs\Web\Controller {
+
+
+ /* @brief Initalize the profile-photo edit view
+ *
+ * @param $a Current application
+ * @return void
+ *
+ */
+
+ 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;
+ }
+
+ check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
+
+ if((x($_POST,'cropfinal')) && ($_POST['cropfinal'] == 1)) {
+
+ // unless proven otherwise
+ $is_default_profile = 1;
+
+ if($_REQUEST['profile']) {
+ $r = q("select id, profile_guid, is_default, gender from profile where id = %d and uid = %d limit 1",
+ intval($_REQUEST['profile']),
+ intval(local_channel())
+ );
+ if($r) {
+ $profile = $r[0];
+ if(! intval($profile['is_default']))
+ $is_default_profile = 0;
+ }
+ }
+
+
+
+ // 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 * FROM photo WHERE resource_id = '%s' AND uid = %d AND scale = %d LIMIT 1",
+ dbesc($image_id),
+ dbesc(local_channel()),
+ intval($scale));
+
+ 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()) {
+
+ $im->cropImage(300,$srcX,$srcY,$srcW,$srcH);
+
+ $aid = get_account_id();
+
+ $p = array('aid' => $aid, 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'],
+ 'filename' => $base_image['filename'], 'album' => t('Profile Photos'));
+
+ $p['scale'] = 4;
+ $p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL);
+
+ $r1 = $im->save($p);
+
+ $im->scaleImage(80);
+ $p['scale'] = 5;
+
+ $r2 = $im->save($p);
+
+ $im->scaleImage(48);
+ $p['scale'] = 6;
+
+ $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 >= 4 ",
+ dbesc($base_image['resource_id']),
+ local_channel()
+ );
+ return;
+ }
+
+ $channel = \App::get_channel();
+
+ // If setting for the default profile, unset the profile photo flag from any other photos I own
+
+ if($is_default_profile) {
+ $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d
+ AND resource_id != '%s' AND `uid` = %d",
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_PROFILE),
+ dbesc($base_image['resource_id']),
+ intval(local_channel())
+ );
+
+ send_profile_photo_activity($channel,$base_image,$profile);
+
+ }
+ else {
+ $r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
+ dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-4'),
+ dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-5'),
+ intval($_REQUEST['profile']),
+ intval(local_channel())
+ );
+ }
+
+ profiles_build_sync(local_channel());
+
+ // We'll set the updated profile-photo timestamp even if it isn't the default profile,
+ // so that browsers will do a cache update unconditionally
+
+
+ $r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s'
+ where xchan_hash = '%s'",
+ dbesc($im->getType()),
+ dbesc(datetime_convert()),
+ dbesc($channel['xchan_hash'])
+ );
+
+ info( t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL);
+
+ // Update directory in background
+ proc_run('php',"include/directory.php",$channel['channel_id']);
+
+ // Now copy profile-permissions to pictures, to prevent privacyleaks by automatically created folder 'Profile Pictures'
+
+ profile_photo_set_profile_perms($_REQUEST['profile']);
+
+
+
+ }
+ else
+ notice( t('Unable to process image') . EOL);
+ }
+
+ goaway(z_root() . '/profiles');
+ return; // NOTREACHED
+ }
+
+
+
+ $hash = photo_new_resource();
+ $smallest = 0;
+
+ require_once('include/attach.php');
+
+ $res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile 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 order by scale",
+ dbesc($hash),
+ intval(local_channel())
+ );
+
+ if(! $i) {
+ notice( t('Image upload failed.') . EOL );
+ return;
+ }
+ $os_storage = false;
+
+ foreach($i as $ii) {
+ if(intval($ii['scale']) < 2) {
+ $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->profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
+
+ }
+
+
+ /* @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('/profile_photo', 'profile_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'] == 5)
+ $havescale = true;
+ }
+
+ // set an already loaded photo as profile photo
+
+ if(($r[0]['album'] == t('Profile Photos')) && ($havescale)) {
+ // unset any existing profile photos
+ $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_PROFILE),
+ intval(local_channel()));
+
+ $r = q("UPDATE photo SET photo_usage = %d WHERE uid = %d AND resource_id = '%s'",
+ intval(PHOTO_PROFILE),
+ intval(local_channel()),
+ dbesc($resource_id)
+ );
+
+ $r = q("UPDATE xchan set xchan_photo_date = '%s'
+ where xchan_hash = '%s'",
+ dbesc(datetime_convert()),
+ dbesc($channel['xchan_hash'])
+ );
+
+ profile_photo_set_profile_perms(); //Reset default photo permissions to public
+ proc_run('php','include/directory.php',local_channel());
+ goaway(z_root() . '/profiles');
+ }
+
+ $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 order by scale",
+ dbesc($r[0]['resource_id']),
+ intval(local_channel())
+ );
+
+ if($i) {
+ $hash = $i[0]['resource_id'];
+ foreach($i as $ii) {
+ if(intval($ii['scale']) < 2) {
+ $smallest = intval($ii['scale']);
+ }
+ }
+ }
+ }
+
+ profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
+ }
+
+ $profiles = q("select id, profile_name as name, is_default from profile where uid = %d",
+ intval(local_channel())
+ );
+
+ if(! x(\App::$data,'imagecrop')) {
+
+ $tpl = get_markup_template('profile_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 Profile Photo'),
+ '$submit' => t('Upload'),
+ '$profiles' => $profiles,
+ '$single' => ((count($profiles) == 1) ? true : false),
+ '$profile0' => $profiles[0],
+ '$form_security_token' => get_form_security_token("profile_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('profile_photo_content_end', $o);
+
+ return $o;
+ }
+ else {
+ $filename = \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution'];
+ $resolution = \App::$data['imagecrop_resolution'];
+ $tpl = get_markup_template("cropbody.tpl");
+ $o .= replace_macros($tpl,array(
+ '$filename' => $filename,
+ '$profile' => intval($_REQUEST['profile']),
+ '$resource' => \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution'],
+ '$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("profile_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 profile_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 < 500 || $height < 500) {
+ $ph->scaleImageUp(400);
+ $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;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php
new file mode 100644
index 000000000..30ec337f8
--- /dev/null
+++ b/Zotlabs/Module/Profiles.php
@@ -0,0 +1,795 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/identity.php');
+
+
+class Profiles extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ nav_set_selected('profiles');
+
+ if(! local_channel()) {
+ return;
+ }
+
+ if((argc() > 2) && (argv(1) === "drop") && intval(argv(2))) {
+ $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d AND `is_default` = 0 LIMIT 1",
+ intval(argv(2)),
+ intval(local_channel())
+ );
+ if(! count($r)) {
+ notice( t('Profile not found.') . EOL);
+ goaway(z_root() . '/profiles');
+ return; // NOTREACHED
+ }
+ $profile_guid = $r['profile_guid'];
+
+ check_form_security_token_redirectOnErr('/profiles', 'profile_drop', 't');
+
+ // move every contact using this profile as their default to the user default
+
+ $r = q("UPDATE abook SET abook_profile = (SELECT profile_guid AS FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1) WHERE abook_profile = '%s' AND abook_channel = %d ",
+ intval(local_channel()),
+ dbesc($profile_guid),
+ intval(local_channel())
+ );
+ $r = q("DELETE FROM `profile` WHERE `id` = %d AND `uid` = %d",
+ intval(argv(2)),
+ intval(local_channel())
+ );
+ if($r)
+ info( t('Profile deleted.') . EOL);
+
+ // @fixme this is a much more complicated sync - add any changed abook entries and
+ // also add deleted flag to profile structure
+ // profiles_build_sync is just here as a placeholder - it doesn't work at all here
+
+ // profiles_build_sync(local_channel());
+
+ goaway(z_root() . '/profiles');
+ return; // NOTREACHED
+ }
+
+
+
+
+
+ if((argc() > 1) && (argv(1) === 'new')) {
+
+ // check_form_security_token_redirectOnErr('/profiles', 'profile_new', 't');
+
+ $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d",
+ intval(local_channel()));
+ $num_profiles = count($r0);
+
+ $name = t('Profile-') . ($num_profiles + 1);
+
+ $r1 = q("SELECT `name`, `photo`, `thumb` FROM `profile` WHERE `uid` = %d AND `is_default` = 1 LIMIT 1",
+ intval(local_channel()));
+
+ $r2 = q("INSERT INTO `profile` (`aid`, `uid` , `profile_guid`, `profile_name` , `name`, `photo`, `thumb`)
+ VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
+ intval(get_account_id()),
+ intval(local_channel()),
+ dbesc(random_string()),
+ dbesc($name),
+ dbesc($r1[0]['name']),
+ dbesc($r1[0]['photo']),
+ dbesc($r1[0]['thumb'])
+ );
+
+ $r3 = q("SELECT `id` FROM `profile` WHERE `uid` = %d AND `profile_name` = '%s' LIMIT 1",
+ intval(local_channel()),
+ dbesc($name)
+ );
+
+ info( t('New profile created.') . EOL);
+ if(count($r3) == 1)
+ goaway(z_root() . '/profiles/' . $r3[0]['id']);
+
+ goaway(z_root() . '/profiles');
+ }
+
+ if((argc() > 2) && (argv(1) === 'clone')) {
+
+ check_form_security_token_redirectOnErr('/profiles', 'profile_clone', 't');
+
+ $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d",
+ intval(local_channel()));
+ $num_profiles = count($r0);
+
+ $name = t('Profile-') . ($num_profiles + 1);
+ $r1 = q("SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d LIMIT 1",
+ intval(local_channel()),
+ intval(\App::$argv[2])
+ );
+ if(! count($r1)) {
+ notice( t('Profile unavailable to clone.') . EOL);
+ \App::$error = 404;
+ return;
+ }
+ unset($r1[0]['id']);
+ $r1[0]['is_default'] = 0;
+ $r1[0]['publish'] = 0;
+ $r1[0]['profile_name'] = dbesc($name);
+ $r1[0]['profile_guid'] = dbesc(random_string());
+
+ dbesc_array($r1[0]);
+
+ $r2 = dbq("INSERT INTO `profile` (`"
+ . implode("`, `", array_keys($r1[0]))
+ . "`) VALUES ('"
+ . implode("', '", array_values($r1[0]))
+ . "')" );
+
+ $r3 = q("SELECT `id` FROM `profile` WHERE `uid` = %d AND `profile_name` = '%s' LIMIT 1",
+ intval(local_channel()),
+ dbesc($name)
+ );
+ info( t('New profile created.') . EOL);
+
+ profiles_build_sync(local_channel());
+
+ if(($r3) && (count($r3) == 1))
+ goaway(z_root() . '/profiles/' . $r3[0]['id']);
+
+ goaway(z_root() . '/profiles');
+
+ return; // NOTREACHED
+ }
+
+ if((argc() > 2) && (argv(1) === 'export')) {
+
+ $r1 = q("SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d LIMIT 1",
+ intval(local_channel()),
+ intval(argv(2))
+ );
+ if(! $r1) {
+ notice( t('Profile unavailable to export.') . EOL);
+ \App::$error = 404;
+ return;
+ }
+ header('content-type: application/octet_stream');
+ header('content-disposition: attachment; filename="' . $r1[0]['profile_name'] . '.json"' );
+
+ unset($r1[0]['id']);
+ unset($r1[0]['aid']);
+ unset($r1[0]['uid']);
+ unset($r1[0]['is_default']);
+ unset($r1[0]['publish']);
+ unset($r1[0]['profile_name']);
+ unset($r1[0]['profile_guid']);
+ echo json_encode($r1[0]);
+ killme();
+ }
+
+
+
+
+ // Run profile_load() here to make sure the theme is set before
+ // we start loading content
+ if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) {
+ if(feature_enabled(local_channel(),'multi_profiles'))
+ $id = \App::$argv[1];
+ else {
+ $x = q("select id from profile where uid = %d and is_default = 1",
+ intval(local_channel())
+ );
+ if($x)
+ $id = $x[0]['id'];
+ }
+ $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+ intval($id),
+ intval(local_channel())
+ );
+ if(! count($r)) {
+ notice( t('Profile not found.') . EOL);
+ \App::$error = 404;
+ return;
+ }
+
+ $chan = \App::get_channel();
+
+ profile_load($a,$chan['channel_address'],$r[0]['id']);
+ }
+ }
+
+ function post() {
+
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ require_once('include/activities.php');
+
+ $namechanged = false;
+
+
+ // import from json export file.
+ // Only import fields that are allowed on this hub
+
+ if(x($_FILES,'userfile')) {
+ $src = $_FILES['userfile']['tmp_name'];
+ $filesize = intval($_FILES['userfile']['size']);
+ if($filesize) {
+ $j = @json_decode(@file_get_contents($src),true);
+ @unlink($src);
+ if($j) {
+ $fields = get_profile_fields_advanced();
+ if($fields) {
+ foreach($j as $jj => $v) {
+ foreach($fields as $f => $n) {
+ if($jj == $f) {
+ $_POST[$f] = $v;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ call_hooks('profile_post', $_POST);
+
+
+ if((argc() > 1) && (argv(1) !== "new") && intval(argv(1))) {
+ $orig = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+ intval(\App::$argv[1]),
+ intval(local_channel())
+ );
+ if(! count($orig)) {
+ notice( t('Profile not found.') . EOL);
+ return;
+ }
+
+ check_form_security_token_redirectOnErr('/profiles', 'profile_edit');
+
+ $is_default = (($orig[0]['is_default']) ? 1 : 0);
+
+ $profile_name = notags(trim($_POST['profile_name']));
+ if(! strlen($profile_name)) {
+ notice( t('Profile Name is required.') . EOL);
+ return;
+ }
+
+ $dob = $_POST['dob'] ? escape_tags(trim($_POST['dob'])) : '0000-00-00'; // FIXME: Needs to be validated?
+
+ $y = substr($dob,0,4);
+ if((! ctype_digit($y)) || ($y < 1900))
+ $ignore_year = true;
+ else
+ $ignore_year = false;
+
+ if($dob != '0000-00-00') {
+ if(strpos($dob,'0000-') === 0) {
+ $ignore_year = true;
+ $dob = substr($dob,5);
+ }
+ $dob = datetime_convert('UTC','UTC',(($ignore_year) ? '1900-' . $dob : $dob),(($ignore_year) ? 'm-d' : 'Y-m-d'));
+ if($ignore_year)
+ $dob = '0000-' . $dob;
+ }
+
+ $name = escape_tags(trim($_POST['name']));
+
+ if($orig[0]['name'] != $name) {
+ $namechanged = true;
+
+ $v = validate_channelname($name);
+ if($v) {
+ notice($v);
+ $namechanged = false;
+ $name = $orig[0]['name'];
+ }
+ }
+
+ $pdesc = escape_tags(trim($_POST['pdesc']));
+ $gender = escape_tags(trim($_POST['gender']));
+ $address = escape_tags(trim($_POST['address']));
+ $locality = escape_tags(trim($_POST['locality']));
+ $region = escape_tags(trim($_POST['region']));
+ $postal_code = escape_tags(trim($_POST['postal_code']));
+ $country_name = escape_tags(trim($_POST['country_name']));
+ $keywords = escape_tags(trim($_POST['keywords']));
+ $marital = escape_tags(trim($_POST['marital']));
+ $howlong = escape_tags(trim($_POST['howlong']));
+ $sexual = escape_tags(trim($_POST['sexual']));
+ $homepage = escape_tags(trim($_POST['homepage']));
+ $hometown = escape_tags(trim($_POST['hometown']));
+ $politic = escape_tags(trim($_POST['politic']));
+ $religion = escape_tags(trim($_POST['religion']));
+
+ $likes = fix_mce_lf(escape_tags(trim($_POST['likes'])));
+ $dislikes = fix_mce_lf(escape_tags(trim($_POST['dislikes'])));
+
+ $about = fix_mce_lf(escape_tags(trim($_POST['about'])));
+ $interest = fix_mce_lf(escape_tags(trim($_POST['interest'])));
+ $contact = fix_mce_lf(escape_tags(trim($_POST['contact'])));
+ $channels = fix_mce_lf(escape_tags(trim($_POST['channels'])));
+ $music = fix_mce_lf(escape_tags(trim($_POST['music'])));
+ $book = fix_mce_lf(escape_tags(trim($_POST['book'])));
+ $tv = fix_mce_lf(escape_tags(trim($_POST['tv'])));
+ $film = fix_mce_lf(escape_tags(trim($_POST['film'])));
+ $romance = fix_mce_lf(escape_tags(trim($_POST['romance'])));
+ $work = fix_mce_lf(escape_tags(trim($_POST['work'])));
+ $education = fix_mce_lf(escape_tags(trim($_POST['education'])));
+
+ $hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0);
+
+ require_once('include/text.php');
+ linkify_tags($a, $likes, local_channel());
+ linkify_tags($a, $dislikes, local_channel());
+ linkify_tags($a, $about, local_channel());
+ linkify_tags($a, $interest, local_channel());
+ linkify_tags($a, $interest, local_channel());
+ linkify_tags($a, $contact, local_channel());
+ linkify_tags($a, $channels, local_channel());
+ linkify_tags($a, $music, local_channel());
+ linkify_tags($a, $book, local_channel());
+ linkify_tags($a, $tv, local_channel());
+ linkify_tags($a, $film, local_channel());
+ linkify_tags($a, $romance, local_channel());
+ linkify_tags($a, $work, local_channel());
+ linkify_tags($a, $education, local_channel());
+
+
+ $with = ((x($_POST,'with')) ? escape_tags(trim($_POST['with'])) : '');
+
+ if(! strlen($howlong))
+ $howlong = NULL_DATE;
+ else
+ $howlong = datetime_convert(date_default_timezone_get(),'UTC',$howlong);
+
+ // linkify the relationship target if applicable
+
+ $withchanged = false;
+
+ if(strlen($with)) {
+ if($with != strip_tags($orig[0]['with'])) {
+ $withchanged = true;
+ $prf = '';
+ $lookup = $with;
+ if(strpos($lookup,'@') === 0)
+ $lookup = substr($lookup,1);
+ $lookup = str_replace('_',' ', $lookup);
+ $newname = $lookup;
+
+ $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE xchan_name = '%s' AND abook_channel = %d LIMIT 1",
+ dbesc($newname),
+ intval(local_channel())
+ );
+ if(! $r) {
+ $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE xchan_addr = '%s' AND abook_channel = %d LIMIT 1",
+ dbesc($lookup . '@%'),
+ intval(local_channel())
+ );
+ }
+ if($r) {
+ $prf = $r[0]['xchan_url'];
+ $newname = $r[0]['xchan_name'];
+ }
+
+
+ if($prf) {
+ $with = str_replace($lookup,'<a href="' . $prf . '">' . $newname . '</a>', $with);
+ if(strpos($with,'@') === 0)
+ $with = substr($with,1);
+ }
+ }
+ else
+ $with = $orig[0]['with'];
+ }
+
+ $profile_fields_basic = get_profile_fields_basic();
+ $profile_fields_advanced = get_profile_fields_advanced();
+ $advanced = ((feature_enabled(local_channel(),'advanced_profiles')) ? true : false);
+ if($advanced)
+ $fields = $profile_fields_advanced;
+ else
+ $fields = $profile_fields_basic;
+
+ $z = q("select * from profdef where true");
+ if($z) {
+ foreach($z as $zz) {
+ if(array_key_exists($zz['field_name'],$fields)) {
+ $w = q("select * from profext where channel_id = %d and hash = '%s' and k = '%s' limit 1",
+ intval(local_channel()),
+ dbesc($orig[0]['profile_guid']),
+ dbesc($zz['field_name'])
+ );
+ if($w) {
+ q("update profext set v = '%s' where id = %d",
+ dbesc(escape_tags(trim($_POST[$zz['field_name']]))),
+ intval($w[0]['id'])
+ );
+ }
+ else {
+ q("insert into profext ( channel_id, hash, k, v ) values ( %d, '%s', '%s', '%s') ",
+ intval(local_channel()),
+ dbesc($orig[0]['profile_guid']),
+ dbesc($zz['field_name']),
+ dbesc(escape_tags(trim($_POST[$zz['field_name']])))
+ );
+ }
+ }
+ }
+ }
+
+ $changes = array();
+ $value = '';
+ if($is_default) {
+ if($marital != $orig[0]['marital']) {
+ $changes[] = '[color=#ff0000]&hearts;[/color] ' . t('Marital Status');
+ $value = $marital;
+ }
+ if($withchanged) {
+ $changes[] = '[color=#ff0000]&hearts;[/color] ' . t('Romantic Partner');
+ $value = strip_tags($with);
+ }
+ if($likes != $orig[0]['likes']) {
+ $changes[] = t('Likes');
+ $value = $likes;
+ }
+ if($dislikes != $orig[0]['dislikes']) {
+ $changes[] = t('Dislikes');
+ $value = $dislikes;
+ }
+ if($work != $orig[0]['work']) {
+ $changes[] = t('Work/Employment');
+ }
+ if($religion != $orig[0]['religion']) {
+ $changes[] = t('Religion');
+ $value = $religion;
+ }
+ if($politic != $orig[0]['politic']) {
+ $changes[] = t('Political Views');
+ $value = $politic;
+ }
+ if($gender != $orig[0]['gender']) {
+ $changes[] = t('Gender');
+ $value = $gender;
+ }
+ if($sexual != $orig[0]['sexual']) {
+ $changes[] = t('Sexual Preference');
+ $value = $sexual;
+ }
+ if($homepage != $orig[0]['homepage']) {
+ $changes[] = t('Homepage');
+ $value = $homepage;
+ }
+ if($interest != $orig[0]['interest']) {
+ $changes[] = t('Interests');
+ $value = $interest;
+ }
+ if($address != $orig[0]['address']) {
+ $changes[] = t('Address');
+ // New address not sent in notifications, potential privacy issues
+ // in case this leaks to unintended recipients. Yes, it's in the public
+ // profile but that doesn't mean we have to broadcast it to everybody.
+ }
+ if($locality != $orig[0]['locality'] || $region != $orig[0]['region']
+ || $country_name != $orig[0]['country_name']) {
+ $changes[] = t('Location');
+ $comma1 = ((($locality) && ($region || $country_name)) ? ', ' : ' ');
+ $comma2 = (($region && $country_name) ? ', ' : '');
+ $value = $locality . $comma1 . $region . $comma2 . $country_name;
+ }
+
+ profile_activity($changes,$value);
+
+ }
+
+ $r = q("UPDATE `profile`
+ SET `profile_name` = '%s',
+ `name` = '%s',
+ `pdesc` = '%s',
+ `gender` = '%s',
+ `dob` = '%s',
+ `address` = '%s',
+ `locality` = '%s',
+ `region` = '%s',
+ `postal_code` = '%s',
+ `country_name` = '%s',
+ `marital` = '%s',
+ `with` = '%s',
+ `howlong` = '%s',
+ `sexual` = '%s',
+ `homepage` = '%s',
+ `hometown` = '%s',
+ `politic` = '%s',
+ `religion` = '%s',
+ `keywords` = '%s',
+ `likes` = '%s',
+ `dislikes` = '%s',
+ `about` = '%s',
+ `interest` = '%s',
+ `contact` = '%s',
+ `channels` = '%s',
+ `music` = '%s',
+ `book` = '%s',
+ `tv` = '%s',
+ `film` = '%s',
+ `romance` = '%s',
+ `work` = '%s',
+ `education` = '%s',
+ `hide_friends` = %d
+ WHERE `id` = %d AND `uid` = %d",
+ dbesc($profile_name),
+ dbesc($name),
+ dbesc($pdesc),
+ dbesc($gender),
+ dbesc($dob),
+ dbesc($address),
+ dbesc($locality),
+ dbesc($region),
+ dbesc($postal_code),
+ dbesc($country_name),
+ dbesc($marital),
+ dbesc($with),
+ dbesc($howlong),
+ dbesc($sexual),
+ dbesc($homepage),
+ dbesc($hometown),
+ dbesc($politic),
+ dbesc($religion),
+ dbesc($keywords),
+ dbesc($likes),
+ dbesc($dislikes),
+ dbesc($about),
+ dbesc($interest),
+ dbesc($contact),
+ dbesc($channels),
+ dbesc($music),
+ dbesc($book),
+ dbesc($tv),
+ dbesc($film),
+ dbesc($romance),
+ dbesc($work),
+ dbesc($education),
+ intval($hide_friends),
+ intval(argv(1)),
+ intval(local_channel())
+ );
+
+ if($r)
+ info( t('Profile updated.') . EOL);
+
+ $r = q("select * from profile where id = %d and uid = %d limit 1",
+ intval(argv(1)),
+ intval(local_channel())
+ );
+ if($r) {
+ require_once('include/zot.php');
+ build_sync_packet(local_channel(),array('profile' => $r));
+ }
+
+ $channel = \App::get_channel();
+
+ if($namechanged && $is_default) {
+ $r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'",
+ dbesc($name),
+ dbesc(datetime_convert()),
+ dbesc($channel['xchan_hash'])
+ );
+ $r = q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'",
+ dbesc($name),
+ dbesc($channel['xchan_hash'])
+ );
+ }
+
+ if($is_default) {
+ // reload the info for the sidebar widget - why does this not work?
+ profile_load($a,$channel['channel_address']);
+ proc_run('php','include/directory.php',local_channel());
+ }
+ }
+ }
+
+
+ function get() {
+
+ $o = '';
+
+ $channel = \App::get_channel();
+
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ require_once('include/identity.php');
+
+ $profile_fields_basic = get_profile_fields_basic();
+ $profile_fields_advanced = get_profile_fields_advanced();
+
+ if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) {
+ if(feature_enabled(local_channel(),'multi_profiles'))
+ $id = \App::$argv[1];
+ else {
+ $x = q("select id from profile where uid = %d and is_default = 1",
+ intval(local_channel())
+ );
+ if($x)
+ $id = $x[0]['id'];
+ }
+ $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+ intval($id),
+ intval(local_channel())
+ );
+ if(! count($r)) {
+ notice( t('Profile not found.') . EOL);
+ return;
+ }
+
+ require_once('include/profile_selectors.php');
+
+
+ $editselect = 'none';
+ // if(feature_enabled(local_channel(),'richtext'))
+ // $editselect = 'textareas';
+
+ \App::$page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), array(
+ '$baseurl' => z_root(),
+ '$editselect' => $editselect,
+ ));
+
+ $advanced = ((feature_enabled(local_channel(),'advanced_profiles')) ? true : false);
+ if($advanced)
+ $fields = $profile_fields_advanced;
+ else
+ $fields = $profile_fields_basic;
+
+ $hide_friends = array(
+ 'hide_friends',
+ t('Hide your connections list from viewers of this profile'),
+ $r[0]['hide_friends'],
+ '',
+ array(t('No'),t('Yes'))
+ );
+
+ $q = q("select * from profdef where true");
+ if($q) {
+ $extra_fields = array();
+
+ foreach($q as $qq) {
+ $mine = q("select v from profext where k = '%s' and hash = '%s' and channel_id = %d limit 1",
+ dbesc($qq['field_name']),
+ dbesc($r[0]['profile_guid']),
+ intval(local_channel())
+ );
+
+ if(array_key_exists($qq['field_name'],$fields)) {
+ $extra_fields[] = array($qq['field_name'],$qq['field_desc'],(($mine) ? $mine[0]['v'] : ''), $qq['field_help']);
+ }
+ }
+ }
+
+ //logger('extra_fields: ' . print_r($extra_fields,true));
+
+ $f = get_config('system','birthday_input_format');
+ if(! $f)
+ $f = 'ymd';
+
+ $is_default = (($r[0]['is_default']) ? 1 : 0);
+
+ $tpl = get_markup_template("profile_edit.tpl");
+ $o .= replace_macros($tpl,array(
+
+ '$form_security_token' => get_form_security_token("profile_edit"),
+ '$profile_clone_link' => ((feature_enabled(local_channel(),'multi_profiles')) ? 'profiles/clone/' . $r[0]['id'] . '?t='
+ . get_form_security_token("profile_clone") : ''),
+ '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t='
+ . get_form_security_token("profile_drop"),
+
+ '$fields' => $fields,
+ '$guid' => $r[0]['profile_guid'],
+ '$banner' => t('Edit Profile Details'),
+ '$submit' => t('Submit'),
+ '$viewprof' => t('View this profile'),
+ '$editvis' => t('Edit visibility'),
+ '$coverpic' => t('Change cover photo'),
+ '$profpic' => t('Change profile photo'),
+ '$cr_prof' => t('Create a new profile using these settings'),
+ '$cl_prof' => t('Clone this profile'),
+ '$del_prof' => t('Delete this profile'),
+ '$addthing' => t('Add profile things'),
+ '$personal' => t('Personal'),
+ '$location' => t('Location'),
+ '$relation' => t('Relation'),
+ '$miscellaneous'=> t('Miscellaneous'),
+ '$exportable' => feature_enabled(local_channel(),'profile_export'),
+ '$lbl_import' => t('Import profile from file'),
+ '$lbl_export' => t('Export profile to file'),
+ '$lbl_gender' => t('Your gender'),
+ '$lbl_marital' => t('Marital status'),
+ '$lbl_sexual' => t('Sexual preference'),
+ '$baseurl' => z_root(),
+ '$profile_id' => $r[0]['id'],
+ '$profile_name' => array('profile_name', t('Profile name'), $r[0]['profile_name'], t('Required'), '*'),
+ '$is_default' => $is_default,
+ '$default' => t('This is your default profile.') . EOL . translate_scope(map_scope($channel['channel_r_profile'])),
+ '$advanced' => $advanced,
+ '$name' => array('name', t('Your full name'), $r[0]['name'], t('Required'), '*'),
+ '$pdesc' => array('pdesc', t('Title/Description'), $r[0]['pdesc']),
+ '$dob' => dob($r[0]['dob']),
+ '$hide_friends' => $hide_friends,
+ '$address' => array('address', t('Street address'), $r[0]['address']),
+ '$locality' => array('locality', t('Locality/City'), $r[0]['locality']),
+ '$region' => array('region', t('Region/State'), $r[0]['region']),
+ '$postal_code' => array('postal_code', t('Postal/Zip code'), $r[0]['postal_code']),
+ '$country_name' => array('country_name', t('Country'), $r[0]['country_name']),
+ '$gender' => gender_selector($r[0]['gender']),
+ '$gender_min' => gender_selector_min($r[0]['gender']),
+ '$marital' => marital_selector($r[0]['marital']),
+ '$marital_min' => marital_selector_min($r[0]['marital']),
+ '$with' => array('with', t("Who (if applicable)"), $r[0]['with'], t('Examples: cathy123, Cathy Williams, cathy@example.com')),
+ '$howlong' => array('howlong', t('Since (date)'), ($r[0]['howlong'] === NULL_DATE ? '' : datetime_convert('UTC',date_default_timezone_get(),$r[0]['howlong']))),
+ '$sexual' => sexpref_selector($r[0]['sexual']),
+ '$sexual_min' => sexpref_selector_min($r[0]['sexual']),
+ '$about' => array('about', t('Tell us about yourself'), $r[0]['about']),
+ '$homepage' => array('homepage', t('Homepage URL'), $r[0]['homepage']),
+ '$hometown' => array('hometown', t('Hometown'), $r[0]['hometown']),
+ '$politic' => array('politic', t('Political views'), $r[0]['politic']),
+ '$religion' => array('religion', t('Religious views'), $r[0]['religion']),
+ '$keywords' => array('keywords', t('Keywords used in directory listings'), $r[0]['keywords'], t('Example: fishing photography software')),
+ '$likes' => array('likes', t('Likes'), $r[0]['likes']),
+ '$dislikes' => array('dislikes', t('Dislikes'), $r[0]['dislikes']),
+ '$music' => array('music', t('Musical interests'), $r[0]['music']),
+ '$book' => array('book', t('Books, literature'), $r[0]['book']),
+ '$tv' => array('tv', t('Television'), $r[0]['tv']),
+ '$film' => array('film', t('Film/Dance/Culture/Entertainment'), $r[0]['film']),
+ '$interest' => array('interest', t('Hobbies/Interests'), $r[0]['interest']),
+ '$romance' => array('romance',t('Love/Romance'), $r[0]['romance']),
+ '$work' => array('work', t('Work/Employment'), $r[0]['work']),
+ '$education' => array('education', t('School/Education'), $r[0]['education']),
+ '$contact' => array('contact', t('Contact information and social networks'), $r[0]['contact']),
+ '$channels' => array('channels', t('My other channels'), $r[0]['channels']),
+ '$extra_fields' => $extra_fields,
+ ));
+
+ $arr = array('profile' => $r[0], 'entry' => $o);
+ call_hooks('profile_edit', $arr);
+
+ return $o;
+ }
+ else {
+
+ $r = q("SELECT * FROM `profile` WHERE `uid` = %d",
+ local_channel());
+ if(count($r)) {
+
+ $tpl = get_markup_template('profile_entry.tpl');
+ foreach($r as $rr) {
+ $profiles .= replace_macros($tpl, array(
+ '$photo' => $rr['thumb'],
+ '$id' => $rr['id'],
+ '$alt' => t('Profile Image'),
+ '$profile_name' => $rr['profile_name'],
+ '$visible' => (($rr['is_default'])
+ ? '<strong>' . translate_scope(map_scope($channel['channel_r_profile'])) . '</strong>'
+ : '<a href="' . z_root() . '/profperm/' . $rr['id'] . '" />' . t('Edit visibility') . '</a>')
+ ));
+ }
+
+ $tpl_header = get_markup_template('profile_listing_header.tpl');
+ $o .= replace_macros($tpl_header,array(
+ '$header' => t('Edit Profiles'),
+ '$cr_new' => t('Create New'),
+ '$cr_new_link' => 'profiles/new?t=' . get_form_security_token("profile_new"),
+ '$profiles' => $profiles
+ ));
+
+
+
+
+ }
+ return $o;
+ }
+
+ }
+
+}
diff --git a/Zotlabs/Module/Profperm.php b/Zotlabs/Module/Profperm.php
new file mode 100644
index 000000000..94267aaac
--- /dev/null
+++ b/Zotlabs/Module/Profperm.php
@@ -0,0 +1,172 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/Contact.php');
+require_once('include/photos.php');
+
+
+class Profperm extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if(! local_channel())
+ return;
+
+ $channel = \App::get_channel();
+ $which = $channel['channel_address'];
+
+ $profile = \App::$argv[1];
+
+ profile_load($a,$which,$profile);
+
+ }
+
+
+ function get() {
+
+ if(! local_channel()) {
+ notice( t('Permission denied') . EOL);
+ return;
+ }
+
+
+ if(argc() < 2) {
+ notice( t('Invalid profile identifier.') . EOL );
+ return;
+ }
+
+ // Switch to text mod 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;
+
+
+ if((argc() > 2) && intval(argv(1)) && intval(argv(2))) {
+ $r = q("SELECT abook_id FROM abook WHERE abook_id = %d and abook_channel = %d limit 1",
+ intval(argv(2)),
+ intval(local_channel())
+ );
+ if($r)
+ $change = intval(argv(2));
+ }
+
+
+ if((argc() > 1) && (intval(argv(1)))) {
+ $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d AND `is_default` = 0 LIMIT 1",
+ intval(argv(1)),
+ intval(local_channel())
+ );
+ if(! $r) {
+ notice( t('Invalid profile identifier.') . EOL );
+ return;
+ }
+
+ $profile = $r[0];
+
+ $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_profile = '%s'",
+ intval(local_channel()),
+ dbesc($profile['profile_guid'])
+ );
+
+ $ingroup = array();
+ if($r)
+ foreach($r as $member)
+ $ingroup[] = $member['abook_id'];
+
+ $members = $r;
+
+ if($change) {
+ if(in_array($change,$ingroup)) {
+ q("UPDATE abook SET abook_profile = '' WHERE abook_id = %d AND abook_channel = %d",
+ intval($change),
+ intval(local_channel())
+ );
+ }
+ else {
+ q("UPDATE abook SET abook_profile = '%s' WHERE abook_id = %d AND abook_channel = %d",
+ dbesc($profile['profile_guid']),
+ intval($change),
+ intval(local_channel())
+ );
+
+ }
+
+
+ //Time to update the permissions on the profile-pictures as well
+
+ profile_photo_set_profile_perms($profile['id']);
+
+ $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_profile = '%s'",
+ intval(local_channel()),
+ dbesc($profile['profile_guid'])
+ );
+
+ $members = $r;
+
+ $ingroup = array();
+ if(count($r))
+ foreach($r as $member)
+ $ingroup[] = $member['abook_id'];
+ }
+
+ $o .= '<h2>' . t('Profile Visibility Editor') . '</h2>';
+
+ $o .= '<h3>' . t('Profile') . ' \'' . $profile['profile_name'] . '\'</h3>';
+
+ $o .= '<div id="prof-edit-desc">' . t('Click on a contact to add or remove.') . '</div>';
+
+ }
+
+ $o .= '<div id="prof-update-wrapper">';
+ if($change)
+ $o = '';
+
+ $o .= '<div id="prof-members-title">';
+ $o .= '<h3>' . t('Visible To') . '</h3>';
+ $o .= '</div>';
+ $o .= '<div id="prof-members">';
+
+ $textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : false);
+
+ foreach($members as $member) {
+ if($member['xchan_url']) {
+ $member['click'] = 'profChangeMember(' . $profile['id'] . ',' . $member['abook_id'] . '); return false;';
+ $o .= micropro($member,true,'mpprof', $textmode);
+ }
+ }
+ $o .= '</div><div id="prof-members-end"></div>';
+ $o .= '<hr id="prof-separator" />';
+
+ $o .= '<div id="prof-all-contcts-title">';
+ $o .= '<h3>' . t("All Connections") . '</h3>';
+ $o .= '</div>';
+ $o .= '<div id="prof-all-contacts">';
+
+ $r = abook_connections(local_channel());
+
+ if($r) {
+ $textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : false);
+ foreach($r as $member) {
+ if(! in_array($member['abook_id'],$ingroup)) {
+ $member['click'] = 'profChangeMember(' . $profile['id'] . ',' . $member['abook_id'] . '); return false;';
+ $o .= micropro($member,true,'mpprof',$textmode);
+ }
+ }
+ }
+
+ $o .= '</div><div id="prof-all-contacts-end"></div>';
+
+ if($change) {
+ echo $o;
+ killme();
+ }
+ $o .= '</div>';
+ return $o;
+
+ }
+
+
+}
diff --git a/Zotlabs/Module/Pubsites.php b/Zotlabs/Module/Pubsites.php
new file mode 100644
index 000000000..559c8f2f1
--- /dev/null
+++ b/Zotlabs/Module/Pubsites.php
@@ -0,0 +1,59 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Pubsites extends \Zotlabs\Web\Controller {
+
+ function get() {
+ require_once('include/dir_fns.php');
+ $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);
+ $url = $directory['url'] . '/dirsearch';
+ }
+ $url .= '/sites';
+
+ $o .= '<div class="generic-content-wrapper">';
+
+ $o .= '<div class="section-title-wrapper"><h2>' . t('Public Hubs') . '</h2></div>';
+
+ $o .= '<div class="section-content-tools-wrapper"><div class="descriptive-text">' .
+ t('The listed hubs allow public registration for the $Projectname network. All hubs in the network are interlinked so membership on any of them conveys membership in the network as a whole. Some hubs may require subscription or provide tiered service plans. The hub itself <strong>may</strong> provide additional details.') . '</div>' . EOL;
+
+ $ret = z_fetch_url($url);
+ if($ret['success']) {
+ $j = json_decode($ret['body'],true);
+ if($j) {
+ $o .= '<table class="table table-striped table-hover"><tr><td>' . t('Hub URL') . '</td><td>' . t('Access Type') . '</td><td>' . t('Registration Policy') . '</td><td colspan="2">' . t('Ratings') . '</td></tr>';
+ if($j['sites']) {
+ foreach($j['sites'] as $jj) {
+ if($jj['project'] !== \Zotlabs\Project\System::get_platform_name())
+ continue;
+ $host = strtolower(substr($jj['url'],strpos($jj['url'],'://')+3));
+ $rate_links = ((local_channel()) ? '<td><a href="rate?f=&target=' . $host . '" class="btn-btn-default"><i class="icon-check"></i> ' . t('Rate') . '</a></td>' : '');
+ $location = '';
+ if(!empty($jj['location'])) {
+ $location = '<p title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="icon-globe"></i> ' . $jj['location'] . '</p>';
+ }
+ else {
+ $location = '<br />&nbsp;';
+ }
+ $urltext = str_replace(array('https://'), '', $jj['url']);
+ $o .= '<tr><td><a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" ><i class="icon-link"></i> ' . $urltext . '</a>' . $location . '</td><td>' . $jj['access'] . '</td><td>' . $jj['register'] . '</td><td><a href="ratings/' . $host . '" class="btn-btn-default"><i class="icon-eye-open"></i> ' . t('View') . '</a></td>' . $rate_links . '</tr>';
+ }
+ }
+
+ $o .= '</table>';
+
+ $o .= '</div></div>';
+
+ }
+ }
+ return $o;
+ }
+
+}
diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php
new file mode 100644
index 000000000..d6cfe6e92
--- /dev/null
+++ b/Zotlabs/Module/Pubstream.php
@@ -0,0 +1,168 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/conversation.php');
+
+
+class Pubstream extends \Zotlabs\Web\Controller {
+
+ function get($update = 0, $load = false) {
+
+ if($load)
+ $_SESSION['loadtime'] = datetime_convert();
+
+
+ if(get_config('system','block_public') && (! get_account_id()) && (! remote_channel())) {
+ return login();
+ }
+
+
+ if(get_config('system','disable_discover_tab'))
+ return;
+
+ $item_normal = item_normal();
+
+ if(! $update) {
+
+ $maxheight = get_config('system','home_divmore_height');
+ if(! $maxheight)
+ $maxheight = 400;
+
+ $o .= '<div id="live-public"></div>' . "\r\n";
+ $o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
+ . "; 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' => 'public',
+ '$uid' => ((local_channel()) ? local_channel() : '0'),
+ '$gid' => '0',
+ '$cid' => '0',
+ '$cmin' => '0',
+ '$cmax' => '99',
+ '$star' => '0',
+ '$liked' => '0',
+ '$conv' => '0',
+ '$spam' => '0',
+ '$fh' => '1',
+ '$nouveau' => '0',
+ '$wall' => '0',
+ '$list' => '0',
+ '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
+ '$search' => '',
+ '$order' => 'comment',
+ '$file' => '',
+ '$cats' => '',
+ '$tags' => '',
+ '$dend' => '',
+ '$mid' => '',
+ '$verb' => '',
+ '$dbegin' => ''
+ ));
+ }
+
+ if($update && ! $load) {
+ // only setup pagination on initial page view
+ $pager_sql = '';
+ }
+ else {
+ \App::set_pager_itemspage(20);
+ $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
+ }
+
+ require_once('include/identity.php');
+ require_once('include/security.php');
+
+ if(get_config('system','site_firehose')) {
+ $uids = " and item.uid in ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) and item_private = 0 and item_wall = 1 ";
+ }
+ else {
+ $sys = get_sys_channel();
+ $uids = " and item.uid = " . intval($sys['channel_id']) . " ";
+ $sql_extra = item_permissions_sql($sys['channel_id']);
+ \App::$data['firehose'] = intval($sys['channel_id']);
+ }
+
+ if(get_config('system','public_list_mode'))
+ $page_mode = 'list';
+ else
+ $page_mode = 'client';
+
+
+ $simple_update = (($update) ? " and item.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 = '';
+
+ //logger('update: ' . $update . ' load: ' . $load);
+
+ if($update) {
+
+ $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.author_xchan = abook.abook_xchan
+ 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 "
+ );
+
+
+ }
+ elseif($update) {
+
+ $r = q("SELECT distinct item.id AS item_id, $ordering FROM item
+ left join abook on item.author_xchan = abook.abook_xchan
+ WHERE true $uids $item_normal
+ AND item.parent = item.id $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,(-1));
+ $items = fetch_post_tags($items,true);
+ $items = conv_sort($items,$ordering);
+ }
+ else {
+ $items = array();
+ }
+
+ }
+
+ // fake it
+ $mode = ('network');
+
+ $o .= conversation($a,$items,$mode,$update,$page_mode);
+
+ if(($items) && (! $update))
+ $o .= alt_pager($a,count($items));
+
+ return $o;
+
+ }
+}
diff --git a/Zotlabs/Module/Randprof.php b/Zotlabs/Module/Randprof.php
new file mode 100644
index 000000000..86b25c22a
--- /dev/null
+++ b/Zotlabs/Module/Randprof.php
@@ -0,0 +1,18 @@
+<?php
+namespace Zotlabs\Module;
+
+
+
+class Randprof extends \Zotlabs\Web\Controller {
+
+ function init() {
+ require_once('include/Contact.php');
+ $x = random_profile();
+ if($x)
+ goaway(chanlink_url($x));
+
+ /** FIXME this doesn't work at the moment as a fallback */
+ goaway(z_root() . '/profile');
+ }
+
+}
diff --git a/Zotlabs/Module/Rate.php b/Zotlabs/Module/Rate.php
new file mode 100644
index 000000000..e2c05b6d4
--- /dev/null
+++ b/Zotlabs/Module/Rate.php
@@ -0,0 +1,178 @@
+<?php
+namespace Zotlabs\Module;
+
+
+
+class Rate extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if(! local_channel())
+ return;
+
+ $channel = \App::get_channel();
+
+ $target = $_REQUEST['target'];
+ if(! $target)
+ return;
+
+ \App::$data['target'] = $target;
+
+ if($target) {
+ $r = q("SELECT * FROM xchan where xchan_hash like '%s' LIMIT 1",
+ dbesc($target)
+ );
+ if($r) {
+ \App::$poi = $r[0];
+ }
+ else {
+ $r = q("select * from site where site_url like '%s' and site_type = %d",
+ dbesc('%' . $target),
+ intval(SITE_TYPE_ZOT)
+ );
+ if($r) {
+ \App::$data['site'] = $r[0];
+ \App::$data['site']['site_url'] = strtolower($r[0]['site_url']);
+ }
+ }
+ }
+
+
+ return;
+
+ }
+
+
+ function post() {
+
+ if(! local_channel())
+ return;
+
+ if(! \App::$data['target'])
+ return;
+
+ if(! $_REQUEST['execute'])
+ return;
+
+ $channel = \App::get_channel();
+
+ $rating = intval($_POST['rating']);
+ if($rating < (-10))
+ $rating = (-10);
+ if($rating > 10)
+ $rating = 10;
+
+ $rating_text = trim(escape_tags($_REQUEST['rating_text']));
+
+ $signed = \App::$data['target'] . '.' . $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(\App::$data['target'])
+ );
+
+ 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(\App::$data['target']),
+ 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(\App::$data['target'])
+ );
+ if($z)
+ $record = $z[0]['xlink_id'];
+ }
+
+ if($record) {
+ proc_run('php','include/ratenotif.php','rating',$record);
+ }
+
+ }
+
+
+
+ function get() {
+
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ // if(! \App::$data['target']) {
+ // notice( t('No recipients.') . EOL);
+ // return;
+ // }
+
+ $poco_rating = get_config('system','poco_rating_enable');
+ if((! $poco_rating) && ($poco_rating !== false)) {
+ notice('Ratings are disabled on this site.');
+ return;
+ }
+
+ $channel = \App::get_channel();
+
+ $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
+ dbesc($channel['channel_hash']),
+ dbesc(\App::$data['target'])
+ );
+ if($r) {
+ \App::$data['xlink'] = $r[0];
+ $rating_val = $r[0]['xlink_rating'];
+ $rating_text = $r[0]['xlink_rating_text'];
+ }
+ else {
+ $rating_val = 0;
+ $rating_text = '';
+ }
+
+ // 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;
+ }
+
+ $o = replace_macros(get_markup_template('rating_form.tpl'),array(
+ '$header' => t('Rating'),
+ '$website' => t('Website:'),
+ '$site' => ((\App::$data['site']) ? '<a href="' . \App::$data['site']['site_url'] . '" >' . \App::$data['site']['site_url'] . '</a>' : ''),
+ 'target' => \App::$data['target'],
+ '$tgt_name' => ((\App::$poi && \App::$poi['xchan_name']) ? \App::$poi['xchan_name'] : sprintf( t('Remote Channel [%s] (not yet known on this site)'), substr(\App::$data['target'],0,16))),
+ '$lbl_rating' => t('Rating (this information is public)'),
+ '$lbl_rating_txt' => t('Optionally explain your rating (this information is public)'),
+ '$rating_txt' => $rating_text,
+ '$rating' => $rating,
+ '$rating_val' => $rating_val,
+ '$slide' => $slide,
+ '$submit' => t('Submit')
+ ));
+
+ return $o;
+
+ }
+}
diff --git a/Zotlabs/Module/Ratings.php b/Zotlabs/Module/Ratings.php
new file mode 100644
index 000000000..802bbfec2
--- /dev/null
+++ b/Zotlabs/Module/Ratings.php
@@ -0,0 +1,115 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/dir_fns.php');
+
+
+class Ratings extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
+ return;
+ }
+
+ if(local_channel())
+ load_contact_links(local_channel());
+
+ $dirmode = intval(get_config('system','directory_mode'));
+
+ $x = find_upstream_directory($dirmode);
+ if($x)
+ $url = $x['url'];
+
+ $poco_rating = get_config('system','poco_rating_enable');
+ // if unset default to enabled
+ if($poco_rating === false)
+ $poco_rating = true;
+
+ if(! $poco_rating)
+ return;
+
+ if(argc() > 1)
+ $hash = argv(1);
+
+ if(! $hash) {
+ notice('Must supply a channel identififier.');
+ return;
+ }
+
+ $results = false;
+
+ $x = z_fetch_url($url . '/ratingsearch/' . urlencode($hash));
+
+
+ if($x['success'])
+ $results = json_decode($x['body'],true);
+
+
+ if((! $results) || (! $results['success'])) {
+
+ notice('No results.');
+ return;
+ }
+
+ if(array_key_exists('xchan_hash',$results['target']))
+ \App::$poi = $results['target'];
+
+ $friends = array();
+ $others = array();
+
+ if($results['ratings']) {
+ foreach($results['ratings'] as $n) {
+ if(is_array(\App::$contacts) && array_key_exists($n['xchan_hash'],\App::$contacts))
+ $friends[] = $n;
+ else
+ $others[] = $n;
+ }
+ }
+
+ \App::$data = array('target' => $results['target'], 'results' => array_merge($friends,$others));
+
+ if(! \App::$data['results']) {
+ notice( t('No ratings') . EOL);
+ }
+
+ return;
+ }
+
+
+
+
+
+ function get() {
+
+ if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
+ notice( t('Public access denied.') . EOL);
+ return;
+ }
+
+ $poco_rating = get_config('system','poco_rating_enable');
+ // if unset default to enabled
+ if($poco_rating === false)
+ $poco_rating = true;
+
+ if(! $poco_rating)
+ return;
+
+ $site_target = ((array_key_exists('target',\App::$data) && array_key_exists('site_url',\App::$data['target'])) ?
+ '<a href="' . \App::$data['target']['site_url'] . '" >' . \App::$data['target']['site_url'] . '</a>' : '');
+
+
+ $o = replace_macros(get_markup_template('prep.tpl'),array(
+ '$header' => t('Ratings'),
+ '$rating_lbl' => t('Rating: ' ),
+ '$website' => t('Website: '),
+ '$site' => $site_target,
+ '$rating_text_lbl' => t('Description: '),
+ '$raters' => \App::$data['results']
+ ));
+
+ return $o;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Ratingsearch.php b/Zotlabs/Module/Ratingsearch.php
new file mode 100644
index 000000000..5f463b378
--- /dev/null
+++ b/Zotlabs/Module/Ratingsearch.php
@@ -0,0 +1,76 @@
+<?php
+namespace Zotlabs\Module;
+
+
+
+class Ratingsearch extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $ret = array('success' => false);
+
+ $dirmode = intval(get_config('system','directory_mode'));
+
+ if($dirmode == DIRECTORY_MODE_NORMAL) {
+ $ret['message'] = 'This site is not a directory server.';
+ json_return_and_die($ret);
+ }
+
+ if(argc() > 1)
+ $hash = argv(1);
+
+ if(! $hash) {
+ $ret['message'] = 'No channel identifier';
+ json_return_and_die($ret);
+ }
+
+ if(strpos($hash,'@')) {
+ $r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
+ dbesc($hash)
+ );
+ if($r)
+ $hash = $r[0]['hubloc_hash'];
+ }
+
+ $p = q("select * from xchan where xchan_hash like '%s'",
+ dbesc($hash . '%')
+ );
+
+ if($p)
+ $target = $p[0]['xchan_hash'];
+ else {
+ $p = q("select * from site where site_url like '%s' and site_type = %d ",
+ dbesc('%' . $hash),
+ intval(SITE_TYPE_ZOT)
+ );
+ if($p) {
+ $target = strtolower($hash);
+ }
+ else {
+ $ret['message'] = 'Rating target not found';
+ json_return_and_die($ret);
+ }
+ }
+
+ if($p)
+ $ret['target'] = $p[0];
+
+ $ret['success'] = true;
+
+ $r = q("select * from xlink left join xchan on xlink_xchan = xchan_hash
+ where xlink_link = '%s' and xlink_rating != 0 and xlink_static = 1 order by xchan_name asc",
+ dbesc($target)
+ );
+
+ if($r) {
+ $ret['ratings'] = $r;
+ }
+ else
+ $ret['ratings'] = array();
+
+ json_return_and_die($ret);
+
+ }
+
+
+}
diff --git a/Zotlabs/Module/Rbmark.php b/Zotlabs/Module/Rbmark.php
new file mode 100644
index 000000000..226cef69e
--- /dev/null
+++ b/Zotlabs/Module/Rbmark.php
@@ -0,0 +1,121 @@
+<?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');
+require_once('include/zot.php');
+require_once('include/bookmarks.php');
+
+/**
+ * remote bookmark
+ *
+ * https://yoursite/rbmark?f=&title=&url=&private=&remote_return=
+ *
+ * This can be called via either GET or POST, use POST for long body content as suhosin often limits GET parameter length
+ *
+ * f= placeholder, often required
+ * title= link text
+ * url= URL to bookmark
+ * ischat=1 if this bookmark is a chatroom
+ * private= Don't share this link
+ * remote_return= absolute URL to return after posting is finished
+ *
+ */
+
+
+class Rbmark extends \Zotlabs\Web\Controller {
+
+ function post() {
+ if($_POST['submit'] !== t('Save'))
+ return;
+
+ logger('rbmark_post: ' . print_r($_REQUEST,true));
+
+ $channel = \App::get_channel();
+
+ $t = array('url' => escape_tags($_REQUEST['url']),'term' => escape_tags($_REQUEST['title']));
+ bookmark_add($channel,$channel,$t,((x($_REQUEST,'private')) ? intval($_REQUEST['private']) : 0),
+ array('menu_id' => ((x($_REQUEST,'menu_id')) ? intval($_REQUEST['menu_id']) : 0),
+ 'menu_name' => ((x($_REQUEST,'menu_name')) ? escape_tags($_REQUEST['menu_name']) : ''),
+ 'ischat' => ((x($_REQUEST['ischat'])) ? intval($_REQUEST['ischat']) : 0)
+ ));
+
+ goaway(z_root() . '/bookmarks');
+
+ }
+
+
+ function get() {
+
+ $o = '';
+
+ if(! local_channel()) {
+
+ // The login procedure is going to bugger our $_REQUEST variables
+ // so save them in the session.
+
+ if(array_key_exists('url',$_REQUEST)) {
+ $_SESSION['bookmark'] = $_REQUEST;
+ }
+ return login();
+ }
+
+ // If we have saved rbmark session variables, but nothing in the current $_REQUEST, recover the saved variables
+
+ if((! array_key_exists('url',$_REQUEST)) && (array_key_exists('bookmark',$_SESSION))) {
+ $_REQUEST = $_SESSION['bookmark'];
+ unset($_SESSION['bookmark']);
+ }
+
+ if($_REQUEST['remote_return']) {
+ $_SESSION['remote_return'] = $_REQUEST['remote_return'];
+ }
+ if(argc() > 1 && argv(1) === 'return') {
+ if($_SESSION['remote_return'])
+ goaway($_SESSION['remote_return']);
+ goaway(z_root() . '/bookmarks');
+ }
+
+ $channel = \App::get_channel();
+
+
+ $m = menu_list($channel['channel_id'],'',MENU_BOOKMARK);
+
+ $menus = array();
+ if($m) {
+ $menus = array(0 => '');
+ foreach($m as $n) {
+ $menus[$n['menu_id']] = $n['menu_name'];
+ }
+ }
+ $menu_select = array('menu_id',t('Select a bookmark folder'),false,'',$menus);
+
+
+ $o .= replace_macros(get_markup_template('rbmark.tpl'), array(
+
+ '$header' => t('Save Bookmark'),
+ '$url' => array('url',t('URL of bookmark'),escape_tags($_REQUEST['url'])),
+ '$title' => array('title',t('Description'),escape_tags($_REQUEST['title'])),
+ '$ischat' => ((x($_REQUEST,'ischat')) ? intval($_REQUEST['ischat']) : 0),
+ '$private' => ((x($_REQUEST,'private')) ? intval($_REQUEST['private']) : 0),
+ '$submit' => t('Save'),
+ '$menu_name' => array('menu_name',t('Or enter new bookmark folder name'),'',''),
+ '$menus' => $menu_select
+
+ ));
+
+
+
+
+
+
+ return $o;
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Regdir.php b/Zotlabs/Module/Regdir.php
new file mode 100644
index 000000000..65f8daf67
--- /dev/null
+++ b/Zotlabs/Module/Regdir.php
@@ -0,0 +1,109 @@
+<?php
+namespace Zotlabs\Module;
+
+/**
+ * With args, register a directory server for this realm.
+ * With no args, return a JSON array of directory servers for this realm.
+ *
+ * @FIXME Not yet implemented: Some realms may require authentication to join their realm.
+ * The RED_GLOBAL realm does not require authentication.
+ * We would then need a flag in the site table to indicate that they've been
+ * validated by the PRIMARY directory for that realm. Sites claiming to be PRIMARY
+ * but are not the realm PRIMARY will be marked invalid.
+ *
+ * @param App &$a
+ */
+
+class Regdir extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $result = array('success' => false);
+
+ $url = $_REQUEST['url'];
+ $access_token = $_REQUEST['t'];
+ $valid = 0;
+
+ // we probably don't need the realm as we will find out in the probe.
+ // What we may want to die is throw an error if you're trying to register in a different realm
+ // so this configuration issue can be discovered.
+
+ $realm = $_REQUEST['realm'];
+ if(! $realm)
+ $realm = DIRECTORY_REALM;
+
+ if($realm === DIRECTORY_REALM) {
+ $valid = 1;
+ } else {
+ $token = get_config('system','realm_token');
+ if($token && $access_token != $token) {
+ $result['message'] = 'This realm requires an access token';
+ return;
+ }
+ $valid = 1;
+ }
+
+ $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);
+ }
+
+ $m = null;
+ if ($url) {
+ $m = parse_url($url);
+
+ if ((! $m) || ((! @dns_get_record($m['host'], DNS_A + DNS_CNAME + DNS_PTR)) && (! filter_var($m['host'], FILTER_VALIDATE_IP) ))) {
+
+ $result['message'] = 'unparseable url';
+ json_return_and_die($result);
+ }
+
+ $f = zot_finger('[system]@' . $m['host']);
+ if($f['success']) {
+ $j = json_decode($f['body'],true);
+ if($j['success'] && $j['guid']) {
+ $x = import_xchan($j);
+ if($x['success']) {
+ $result['success'] = true;
+ }
+ }
+ }
+
+ if(! $result['success'])
+ $valid = 0;
+
+ q("update site set site_valid = %d where site_url = '%s' limit 1",
+ intval($valid),
+ strtolower($url)
+ );
+
+ json_return_and_die($result);
+ } else {
+
+ // We can put this in the sql without the condition after 31 august 2015 assuming
+ // most directory servers will have updated by then
+ // This just makes sure it happens if I forget
+
+ $sql_extra = ((datetime_convert() > datetime_convert('UTC','UTC','2015-08-31')) ? ' and site_valid = 1 ' : '' );
+ if ($dirmode == DIRECTORY_MODE_STANDALONE) {
+ $r = array(array('site_url' => z_root()));
+ } else {
+ $r = q("select site_url from site where site_flags in ( 1, 2 ) and site_realm = '%s' and site_type = %d $sql_extra ",
+ dbesc(get_directory_realm()),
+ intval(SITE_TYPE_ZOT)
+ );
+ }
+ if ($r) {
+ $result['success'] = true;
+ $result['directories'] = array();
+ foreach ($r as $rr)
+ $result['directories'][] = $rr['site_url'];
+
+ json_return_and_die($result);
+ }
+ }
+ json_return_and_die($result);
+ }
+}
diff --git a/Zotlabs/Module/Register.php b/Zotlabs/Module/Register.php
new file mode 100644
index 000000000..ca3f33238
--- /dev/null
+++ b/Zotlabs/Module/Register.php
@@ -0,0 +1,270 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/identity.php');
+
+
+class Register extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $result = null;
+ $cmd = ((argc() > 1) ? argv(1) : '');
+
+ // Provide a stored request for somebody desiring a connection
+ // when they first need to register someplace. Once they've
+ // created a channel, we'll try to revive the connection request
+ // and process it.
+
+ if($_REQUEST['connect'])
+ $_SESSION['connect'] = $_REQUEST['connect'];
+
+ switch($cmd) {
+ case 'invite_check.json':
+ $result = check_account_invite($_REQUEST['invite_code']);
+ break;
+ case 'email_check.json':
+ $result = check_account_email($_REQUEST['email']);
+ break;
+ case 'password_check.json':
+ $result = check_account_password($_REQUEST['password']);
+ break;
+ default:
+ break;
+ }
+ if($result) {
+ json_return_and_die($result);
+ }
+ }
+
+
+ function post() {
+
+ $max_dailies = intval(get_config('system','max_daily_registrations'));
+ if($max_dailies) {
+ $r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s",
+ db_utcnow(), db_quoteinterval('1 day')
+ );
+ if($r && $r[0]['total'] >= $max_dailies) {
+ notice( t('Maximum daily site registrations exceeded. Please try again tomorrow.') . EOL);
+ return;
+ }
+ }
+
+ if(! x($_POST,'tos')) {
+ notice( t('Please indicate acceptance of the Terms of Service. Registration failed.') . EOL);
+ return;
+ }
+
+ $policy = get_config('system','register_policy');
+
+ $email_verify = get_config('system','verify_email');
+
+
+ switch($policy) {
+
+ case REGISTER_OPEN:
+ $flags = ACCOUNT_OK;
+ break;
+
+ case REGISTER_APPROVE:
+ $flags = ACCOUNT_BLOCKED | ACCOUNT_PENDING;
+ break;
+
+ default:
+ case REGISTER_CLOSED:
+ if(! is_site_admin()) {
+ notice( t('Permission denied.') . EOL );
+ return;
+ }
+ $flags = ACCOUNT_BLOCKED;
+ break;
+ }
+
+ if($email_verify && $policy == REGISTER_OPEN)
+ $flags = $flags | ACCOUNT_UNVERIFIED;
+
+
+ if((! $_POST['password']) || ($_POST['password'] !== $_POST['password2'])) {
+ notice( t('Passwords do not match.') . EOL);
+ return;
+ }
+
+ $arr = $_POST;
+ $arr['account_flags'] = $flags;
+
+ $result = create_account($arr);
+
+ if(! $result['success']) {
+ notice($result['message']);
+ return;
+ }
+ require_once('include/security.php');
+
+
+ if($_REQUEST['name'])
+ set_aconfig($result['account']['account_id'],'register','channel_name',$_REQUEST['name']);
+ if($_REQUEST['nickname'])
+ set_aconfig($result['account']['account_id'],'register','channel_address',$_REQUEST['nickname']);
+ if($_REQUEST['permissions_role'])
+ set_aconfig($result['account']['account_id'],'register','permissions_role',$_REQUEST['permissions_role']);
+
+
+ $using_invites = intval(get_config('system','invitation_only'));
+ $num_invites = intval(get_config('system','number_invites'));
+ $invite_code = ((x($_POST,'invite_code')) ? notags(trim($_POST['invite_code'])) : '');
+
+ if($using_invites && $invite_code) {
+ q("delete * from register where hash = '%s'", dbesc($invite_code));
+ // @FIXME - this also needs to be considered when using 'invites_remaining' in mod/invite.php
+ set_aconfig($result['account']['account_id'],'system','invites_remaining',$num_invites);
+ }
+
+ if($policy == REGISTER_OPEN ) {
+ if($email_verify) {
+ $res = verify_email_address($result);
+ }
+ else {
+ $res = send_register_success_email($result['email'],$result['password']);
+ }
+ if($res) {
+ info( t('Registration successful. Please check your email for validation instructions.') . EOL ) ;
+ }
+ }
+ elseif($policy == REGISTER_APPROVE) {
+ $res = send_reg_approval_email($result);
+ if($res) {
+ info( t('Your registration is pending approval by the site owner.') . EOL ) ;
+ }
+ else {
+ notice( t('Your registration can not be processed.') . EOL);
+ }
+ goaway(z_root());
+ }
+
+ if($email_verify) {
+ goaway(z_root());
+ }
+
+ authenticate_success($result['account'],true,false,true);
+
+ $new_channel = false;
+ $next_page = 'new_channel';
+
+ if(get_config('system','auto_channel_create') || UNO) {
+ $new_channel = auto_channel_create($result['account']['account_id']);
+ if($new_channel['success']) {
+ $channel_id = $new_channel['channel']['channel_id'];
+ change_channel($channel_id);
+ $next_page = '~';
+ }
+ else
+ $new_channel = false;
+ }
+
+ $x = get_config('system','workflow_register_next');
+ if($x) {
+ $next_page = $x;
+ $_SESSION['workflow'] = true;
+ }
+
+ goaway(z_root() . '/' . $next_page);
+
+ }
+
+
+
+ function get() {
+
+ $registration_is = '';
+ $other_sites = '';
+
+ if(get_config('system','register_policy') == REGISTER_CLOSED) {
+ if(get_config('system','directory_mode') == DIRECTORY_MODE_STANDALONE) {
+ notice( t('Registration on this hub is disabled.') . EOL);
+ return;
+ }
+
+ $mod = new Pubsites();
+ return $mod->get();
+ }
+
+ if(get_config('system','register_policy') == REGISTER_APPROVE) {
+ $registration_is = t('Registration on this hub is by approval only.');
+ $other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>');
+ }
+
+ $max_dailies = intval(get_config('system','max_daily_registrations'));
+ if($max_dailies) {
+ $r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s",
+ db_utcnow(), db_quoteinterval('1 day')
+ );
+ if($r && $r[0]['total'] >= $max_dailies) {
+ logger('max daily registrations exceeded.');
+ notice( t('This site has exceeded the number of allowed daily account registrations. Please try again tomorrow.') . EOL);
+ return;
+ }
+ }
+
+ // Configurable terms of service link
+
+ $tosurl = get_config('system','tos_url');
+ if(! $tosurl)
+ $tosurl = z_root() . '/help/TermsOfService';
+
+ $toslink = '<a href="' . $tosurl . '" target="_blank">' . t('Terms of Service') . '</a>';
+
+ // Configurable whether to restrict age or not - default is based on international legal requirements
+ // This can be relaxed if you are on a restricted server that does not share with public servers
+
+ if(get_config('system','no_age_restriction'))
+ $label_tos = sprintf( t('I accept the %s for this website'), $toslink);
+ else
+ $label_tos = sprintf( t('I am over 13 years of age and accept the %s for this website'), $toslink);
+
+ $enable_tos = 1 - intval(get_config('system','no_termsofservice'));
+
+ $email = array('email', t('Your email address'), ((x($_REQUEST,'email')) ? strip_tags(trim($_REQUEST['email'])) : ""));
+ $password = array('password', t('Choose a password'), ((x($_REQUEST,'password')) ? trim($_REQUEST['password']) : ""));
+ $password2 = array('password2', t('Please re-enter your password'), ((x($_REQUEST,'password2')) ? trim($_REQUEST['password2']) : ""));
+ $invite_code = array('invite_code', t('Please enter your invitation code'), ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : ""));
+ $name = array('name', t('Name or caption'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"'));
+ $nickhub = '@' . str_replace(array('http://','https://','/'), '', get_config('system','baseurl'));
+ $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub));
+ $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());
+ $tos = array('tos', $label_tos, '', '', array(t('no'),t('yes')));
+
+ $auto_create = ((UNO) || (get_config('system','auto_channel_create')) ? true : false);
+ $default_role = ((UNO) ? 'social' : get_config('system','default_permissions_role'));
+
+ require_once('include/bbcode.php');
+
+ $o = replace_macros(get_markup_template('register.tpl'), array(
+
+ '$title' => t('Registration'),
+ '$reg_is' => $registration_is,
+ '$registertext' => bbcode(get_config('system','register_text')),
+ '$other_sites' => $other_sites,
+ '$invitations' => get_config('system','invitation_only'),
+ '$invite_desc' => t('Membership on this site is by invitation only.'),
+ '$invite_code' => $invite_code,
+ '$auto_create' => $auto_create,
+ '$name' => $name,
+ '$role' => $role,
+ '$default_role' => $default_role,
+ '$nickname' => $nickname,
+ '$enable_tos' => $enable_tos,
+ '$tos' => $tos,
+ '$email' => $email,
+ '$pass1' => $password,
+ '$pass2' => $password2,
+ '$submit' => ((UNO || $auto_create || $registration_is) ? t('Register') : t('Proceed to create your first channel'))
+ ));
+
+ return $o;
+
+ }
+
+
+}
diff --git a/Zotlabs/Module/Regmod.php b/Zotlabs/Module/Regmod.php
new file mode 100644
index 000000000..c7e5c44aa
--- /dev/null
+++ b/Zotlabs/Module/Regmod.php
@@ -0,0 +1,40 @@
+<?php
+namespace Zotlabs\Module;
+
+
+
+class Regmod extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ global $lang;
+
+ $_SESSION['return_url'] = \App::$cmd;
+
+ if(! local_channel()) {
+ info( t('Please login.') . EOL);
+ $o .= '<br /><br />' . login((\App::$config['system']['register_policy'] == REGISTER_CLOSED) ? 0 : 1);
+ return $o;
+ }
+
+ if(! is_site_admin()) {
+ notice( t('Permission denied.') . EOL);
+ return '';
+ }
+
+ if(argc() != 3)
+ killme();
+
+ $cmd = argv(1);
+ $hash = argv(2);
+
+ if($cmd === 'deny') {
+ if (! account_deny($hash)) killme();
+ }
+
+ if($cmd === 'allow') {
+ if (! account_allow($hash)) killme();
+ }
+ }
+
+}
diff --git a/Zotlabs/Module/Regver.php b/Zotlabs/Module/Regver.php
new file mode 100644
index 000000000..82b162f56
--- /dev/null
+++ b/Zotlabs/Module/Regver.php
@@ -0,0 +1,28 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Regver extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ global $lang;
+
+ $_SESSION['return_url'] = \App::$cmd;
+
+ if(argc() != 3)
+ killme();
+
+ $cmd = argv(1);
+ $hash = argv(2);
+
+ if($cmd === 'deny') {
+ if (! account_deny($hash)) killme();
+ }
+
+ if($cmd === 'allow') {
+ if (! account_approve($hash)) killme();
+ }
+ }
+
+}
diff --git a/Zotlabs/Module/Removeaccount.php b/Zotlabs/Module/Removeaccount.php
new file mode 100644
index 000000000..da496dfad
--- /dev/null
+++ b/Zotlabs/Module/Removeaccount.php
@@ -0,0 +1,72 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Removeaccount extends \Zotlabs\Web\Controller {
+
+ function post() {
+
+ if(! local_channel())
+ return;
+
+ if($_SESSION['delegate'])
+ return;
+
+ if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password']))))
+ return;
+
+ if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify']))))
+ return;
+
+ if($_POST['verify'] !== $_SESSION['remove_account_verify'])
+ return;
+
+
+ $account = \App::get_account();
+ $account_id = get_account_id();
+
+ if(! account_verify_password($account['account_email'],$_POST['qxz_password']))
+ return;
+
+ if($account['account_password_changed'] != NULL_DATE) {
+ $d1 = datetime_convert('UTC','UTC','now - 48 hours');
+ if($account['account_password_changed'] > d1) {
+ notice( t('Account removals are not allowed within 48 hours of changing the account password.') . EOL);
+ return;
+ }
+ }
+
+ require_once('include/Contact.php');
+
+ $global_remove = intval($_POST['global']);
+
+ account_remove($account_id,true);
+
+ }
+
+
+
+ function get() {
+
+ if(! local_channel())
+ goaway(z_root());
+
+ $hash = random_string();
+
+ $_SESSION['remove_account_verify'] = $hash;
+ $tpl = get_markup_template('removeaccount.tpl');
+ $o .= replace_macros($tpl, array(
+ '$basedir' => z_root(),
+ '$hash' => $hash,
+ '$title' => t('Remove This Account'),
+ '$desc' => array(t('WARNING: '), t('This account and all its channels will be completely removed from the network. '), t('This action is permanent and can not be undone!')),
+ '$passwd' => t('Please enter your password for verification:'),
+ '$global' => array('global', t('Remove this account, all its channels and all its channel clones from the network'), false, t('By default only the instances of the channels located on this hub will be removed from the network')),
+ '$submit' => t('Remove Account')
+ ));
+
+ return $o;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Removeme.php b/Zotlabs/Module/Removeme.php
new file mode 100644
index 000000000..9b634672a
--- /dev/null
+++ b/Zotlabs/Module/Removeme.php
@@ -0,0 +1,72 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Removeme extends \Zotlabs\Web\Controller {
+
+ function post() {
+
+ if(! local_channel())
+ return;
+
+ if($_SESSION['delegate'])
+ return;
+
+ if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password']))))
+ return;
+
+ if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify']))))
+ return;
+
+ if($_POST['verify'] !== $_SESSION['remove_account_verify'])
+ return;
+
+
+ $account = \App::get_account();
+
+ if(! account_verify_password($account['account_email'],$_POST['qxz_password']))
+ return;
+
+ if($account['account_password_changed'] != NULL_DATE) {
+ $d1 = datetime_convert('UTC','UTC','now - 48 hours');
+ if($account['account_password_changed'] > d1) {
+ notice( t('Channel removals are not allowed within 48 hours of changing the account password.') . EOL);
+ return;
+ }
+ }
+
+ require_once('include/Contact.php');
+
+ $global_remove = intval($_POST['global']);
+
+ channel_remove(local_channel(),1 - $global_remove,true);
+
+ }
+
+
+
+ function get() {
+
+ if(! local_channel())
+ goaway(z_root());
+
+ $hash = random_string();
+
+ $_SESSION['remove_account_verify'] = $hash;
+
+ $tpl = get_markup_template('removeme.tpl');
+ $o .= replace_macros($tpl, array(
+ '$basedir' => z_root(),
+ '$hash' => $hash,
+ '$title' => t('Remove This Channel'),
+ '$desc' => array(t('WARNING: '), t('This channel will be completely removed from the network. '), t('This action is permanent and can not be undone!')),
+ '$passwd' => t('Please enter your password for verification:'),
+ '$global' => array('global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network'), array(t('No'),t('Yes'))),
+ '$submit' => t('Remove Channel')
+ ));
+
+ return $o;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Rmagic.php b/Zotlabs/Module/Rmagic.php
new file mode 100644
index 000000000..bcdbf6c90
--- /dev/null
+++ b/Zotlabs/Module/Rmagic.php
@@ -0,0 +1,95 @@
+<?php
+namespace Zotlabs\Module;
+
+
+
+class Rmagic extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if(local_channel())
+ goaway(z_root());
+
+ $me = get_my_address();
+ if($me) {
+ $r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1",
+ dbesc($me)
+ );
+ if($r) {
+ if($r[0]['hubloc_url'] === z_root())
+ goaway(z_root() . '/login');
+ $dest = z_root() . '/' . str_replace('zid=','zid_=',\App::$query_string);
+ goaway($r[0]['hubloc_url'] . '/magic' . '?f=&dest=' . $dest);
+ }
+ }
+ }
+
+ function post() {
+
+ $address = trim($_REQUEST['address']);
+
+ if(strpos($address,'@') === false) {
+ $arr = array('address' => $address);
+ call_hooks('reverse_magic_auth', $arr);
+
+ try {
+ require_once('library/openid/openid.php');
+ $openid = new LightOpenID(z_root());
+ $openid->identity = $address;
+ $openid->returnUrl = z_root() . '/openid';
+ $openid->required = array('namePerson/friendly', 'namePerson');
+ $openid->optional = array('namePerson/first','media/image/aspect11','media/image/default');
+ goaway($openid->authUrl());
+ } catch (Exception $e) {
+ notice( t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.').'<br /><br >'. t('The error message was:').' '.$e->getMessage());
+ }
+
+ // if they're still here...
+ notice( t('Authentication failed.') . EOL);
+ return;
+ }
+ else {
+
+ // Presumed Red identity. Perform reverse magic auth
+
+ if(strpos($address,'@') === false) {
+ notice('Invalid address.');
+ return;
+ }
+
+ $r = null;
+ if($address) {
+ $r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1",
+ dbesc($address)
+ );
+ }
+ if($r) {
+ $url = $r[0]['hubloc_url'];
+ }
+ else {
+ $url = 'https://' . substr($address,strpos($address,'@')+1);
+ }
+
+ if($url) {
+ if($_SESSION['return_url'])
+ $dest = urlencode(z_root() . '/' . str_replace('zid=','zid_=',$_SESSION['return_url']));
+ else
+ $dest = urlencode(z_root() . '/' . str_replace('zid=','zid_=',\App::$query_string));
+
+ goaway($url . '/magic' . '?f=&dest=' . $dest);
+ }
+ }
+ }
+
+
+ function get() {
+
+ $o = replace_macros(get_markup_template('rmagic.tpl'),array(
+ '$title' => t('Remote Authentication'),
+ '$desc' => t('Enter your channel address (e.g. channel@example.com)'),
+ '$submit' => t('Authenticate')
+ ));
+ return $o;
+
+ }
+}
diff --git a/Zotlabs/Module/Rpost.php b/Zotlabs/Module/Rpost.php
new file mode 100644
index 000000000..195949e1c
--- /dev/null
+++ b/Zotlabs/Module/Rpost.php
@@ -0,0 +1,144 @@
+<?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');
+require_once('include/zot.php');
+
+/**
+ * remote post
+ *
+ * https://yoursite/rpost?f=&title=&body=&remote_return=
+ *
+ * This can be called via either GET or POST, use POST for long body content as suhosin often limits GET parameter length
+ *
+ * f= placeholder, often required
+ * title= Title of post
+ * body= Body of post
+ * url= URL which will be parsed and the results appended to the body
+ * source= Source application
+ * remote_return= absolute URL to return after posting is finished
+ * type= choices are 'html' or 'bbcode', default is 'bbcode'
+ *
+ */
+
+
+
+
+class Rpost extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ $o = '';
+
+ if(! local_channel()) {
+ if(remote_channel()) {
+ // redirect to your own site.
+ // We can only do this with a GET request so you'll need to keep the text short or risk getting truncated
+ // by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin
+ // blocks them.
+
+ $url = get_rpost_path(\App::get_observer());
+ // make sure we're not looping to our own hub
+ if(($url) && (! stristr($url, \App::get_hostname()))) {
+ foreach($_REQUEST as $key => $arg) {
+ $url .= '&' . $key . '=' . $arg;
+ }
+ goaway($url);
+ }
+ }
+
+ // The login procedure is going to bugger our $_REQUEST variables
+ // so save them in the session.
+
+ if(array_key_exists('body',$_REQUEST)) {
+ $_SESSION['rpost'] = $_REQUEST;
+ }
+ return login();
+ }
+
+ // If we have saved rpost session variables, but nothing in the current $_REQUEST, recover the saved variables
+
+ if((! array_key_exists('body',$_REQUEST)) && (array_key_exists('rpost',$_SESSION))) {
+ $_REQUEST = $_SESSION['rpost'];
+ unset($_SESSION['rpost']);
+ }
+
+ if(array_key_exists('channel',$_REQUEST)) {
+ $r = q("select channel_id from channel where channel_account_id = %d and channel_address = '%s' limit 1",
+ intval(get_account_id()),
+ dbesc($_REQUEST['channel'])
+ );
+ if($r) {
+ require_once('include/security.php');
+ $change = change_channel($r[0]['channel_id']);
+ }
+ }
+
+ if($_REQUEST['remote_return']) {
+ $_SESSION['remote_return'] = $_REQUEST['remote_return'];
+ }
+ if(argc() > 1 && argv(1) === 'return') {
+ if($_SESSION['remote_return'])
+ goaway($_SESSION['remote_return']);
+ goaway(z_root() . '/network');
+ }
+
+ $plaintext = true;
+ // if(feature_enabled(local_channel(),'richtext'))
+ // $plaintext = false;
+
+ if(array_key_exists('type', $_REQUEST) && $_REQUEST['type'] === 'html') {
+ require_once('include/html2bbcode.php');
+ $_REQUEST['body'] = html2bbcode($_REQUEST['body']);
+ }
+
+ $channel = \App::get_channel();
+
+
+ $acl = new \Zotlabs\Access\AccessList($channel);
+
+ $channel_acl = $acl->get();
+
+ if($_REQUEST['url']) {
+ $x = z_fetch_url(z_root() . '/linkinfo?f=&url=' . urlencode($_REQUEST['url']));
+ if($x['success'])
+ $_REQUEST['body'] = $_REQUEST['body'] . $x['body'];
+ }
+
+ $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' => (($acl->is_private()) ? 'lock' : 'unlock'),
+ 'acl' => populate_acl($channel_acl,true,(($channel['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : '')),
+ 'bang' => '',
+ 'visitor' => true,
+ 'profile_uid' => local_channel(),
+ 'title' => $_REQUEST['title'],
+ 'body' => $_REQUEST['body'],
+ 'attachment' => $_REQUEST['attachment'],
+ 'source' => ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : ''),
+ 'return_path' => 'rpost/return',
+ 'bbco_autocomplete' => 'bbcode',
+ '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;
+
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Rsd_xml.php b/Zotlabs/Module/Rsd_xml.php
new file mode 100644
index 000000000..06af39ad1
--- /dev/null
+++ b/Zotlabs/Module/Rsd_xml.php
@@ -0,0 +1,17 @@
+<?php
+namespace Zotlabs\Module;
+
+class Rsd_xml extends \Zotlabs\Web\Controller {
+
+ function init() {
+ header ("Content-Type: text/xml");
+ echo replace_macros(get_markup_template('rsd.tpl'),array(
+ '$project' => \Zotlabs\Project\System::get_platform_name(),
+ '$baseurl' => z_root(),
+ '$apipath' => z_root() . '/api/'
+ ));
+ killme();
+ }
+
+}
+
diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php
new file mode 100644
index 000000000..9941ebbd2
--- /dev/null
+++ b/Zotlabs/Module/Search.php
@@ -0,0 +1,228 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Search extends \Zotlabs\Web\Controller {
+
+ function init() {
+ if(x($_REQUEST,'search'))
+ \App::$data['search'] = $_REQUEST['search'];
+ }
+
+
+ function get($update = 0, $load = false) {
+
+ if((get_config('system','block_public')) || (get_config('system','block_public_search'))) {
+ if ((! local_channel()) && (! remote_channel())) {
+ notice( t('Public access denied.') . EOL);
+ return;
+ }
+ }
+
+ if($load)
+ $_SESSION['loadtime'] = datetime_convert();
+
+ nav_set_selected('search');
+
+ require_once("include/bbcode.php");
+ require_once('include/security.php');
+ require_once('include/conversation.php');
+ require_once('include/items.php');
+
+ $format = (($_REQUEST['format']) ? $_REQUEST['format'] : '');
+ if($format !== '') {
+ $update = $load = 1;
+ }
+
+ $observer = \App::get_observer();
+ $observer_hash = (($observer) ? $observer['xchan_hash'] : '');
+
+ $o = '<div id="live-search"></div>' . "\r\n";
+
+ $o = '<div class="generic-content-wrapper-styled">' . "\r\n";
+
+ $o .= '<h3>' . t('Search') . '</h3>';
+
+ if(x(\App::$data,'search'))
+ $search = trim(\App::$data['search']);
+ else
+ $search = ((x($_GET,'search')) ? trim(rawurldecode($_GET['search'])) : '');
+
+ $tag = false;
+ if(x($_GET,'tag')) {
+ $tag = true;
+ $search = ((x($_GET,'tag')) ? trim(rawurldecode($_GET['tag'])) : '');
+ }
+
+ if((! local_channel()) || (! feature_enabled(local_channel(),'savedsearch')))
+ $o .= search($search,'search-box','/search',((local_channel()) ? true : false));
+
+ if(strpos($search,'#') === 0) {
+ $tag = true;
+ $search = substr($search,1);
+ }
+ if(strpos($search,'@') === 0) {
+ $search = substr($search,1);
+ goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search);
+ }
+ if(strpos($search,'?') === 0) {
+ $search = substr($search,1);
+ goaway(z_root() . '/help' . '?f=1&navsearch=1&search=' . $search);
+ }
+
+ // look for a naked webbie
+ if(strpos($search,'@') !== false) {
+ goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search);
+ }
+
+ if(! $search)
+ return $o;
+
+ if($tag) {
+ $sql_extra = sprintf(" AND `item`.`id` IN (select `oid` from term where otype = %d and type in ( %d , %d) and term = '%s') ",
+ intval(TERM_OBJ_POST),
+ intval(TERM_HASHTAG),
+ intval(TERM_COMMUNITYTAG),
+ dbesc(protect_sprintf($search))
+ );
+ }
+ else {
+ $regstr = db_getfunc('REGEXP');
+ $sql_extra = sprintf(" AND `item`.`body` $regstr '%s' ", dbesc(protect_sprintf(preg_quote($search))));
+ }
+
+ // Here is the way permissions work in the search module...
+ // Only public posts can be shown
+ // OR your own posts if you are a logged in member
+ // No items will be shown if the member has a blocked profile wall.
+
+ 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.
+
+ $o .= '<div id="live-search"></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' => 'search',
+ '$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',
+ '$fh' => '0',
+ '$nouveau' => '0',
+ '$wall' => '0',
+ '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
+ '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
+ '$search' => (($tag) ? urlencode('#') : '') . $search,
+ '$order' => '',
+ '$file' => '',
+ '$cats' => '',
+ '$tags' => '',
+ '$mid' => '',
+ '$verb' => '',
+ '$dend' => '',
+ '$dbegin' => ''
+ ));
+
+
+ }
+
+ $item_normal = item_normal();
+ $pub_sql = public_permissions_sql($observer_hash);
+
+ require_once('include/identity.php');
+
+ $sys = get_sys_channel();
+
+ if(($update) && ($load)) {
+ $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']));
+
+ // in case somebody turned off public access to sys channel content with permissions
+
+ if(! perm_is_allowed($sys['channel_id'],$observer_hash,'view_stream'))
+ $sys['xchan_hash'] .= 'disabled';
+
+ if($load) {
+ $r = null;
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $prefix = 'distinct on (created, mid)';
+ $suffix = 'ORDER BY created DESC, mid';
+ } else {
+ $prefix = 'distinct';
+ $suffix = 'group by mid ORDER BY created DESC';
+ }
+ if(local_channel()) {
+ $r = q("SELECT $prefix mid, item.id as item_id, item.* from item
+ WHERE ((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' AND item_private = 0 )
+ OR ( `item`.`uid` = %d )) OR item.owner_xchan = '%s' )
+ $item_normal
+ $sql_extra
+ $suffix $pager_sql ",
+ intval(local_channel()),
+ dbesc($sys['xchan_hash'])
+ );
+ }
+ if($r === null) {
+ $r = q("SELECT $prefix mid, item.id as item_id, item.* from item
+ WHERE (((( `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) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
+ $pub_sql ) OR owner_xchan = '%s')
+ $item_normal
+ $sql_extra
+ $suffix $pager_sql",
+ dbesc($sys['xchan_hash'])
+ );
+ }
+ }
+ else {
+ $r = array();
+ }
+ }
+
+ if($r) {
+ xchan_query($r);
+ $items = fetch_post_tags($r,true);
+ } else {
+ $items = array();
+ }
+
+
+ if($format == 'json') {
+ $result = array();
+ require_once('include/conversation.php');
+ foreach($items as $item) {
+ $item['html'] = bbcode($item['body']);
+ $x = encode_item($item);
+ $x['html'] = prepare_text($item['body'],$item['mimetype']);
+ $result[] = $x;
+ }
+ json_return_and_die(array('success' => true,'messages' => $result));
+ }
+
+ if($tag)
+ $o .= '<h2>' . sprintf( t('Items tagged with: %s'),htmlspecialchars($search, ENT_COMPAT,'UTF-8')) . '</h2>';
+ else
+ $o .= '<h2>' . sprintf( t('Search results for: %s'),htmlspecialchars($search, ENT_COMPAT,'UTF-8')) . '</h2>';
+
+ $o .= conversation($a,$items,'search',$update,'client');
+
+ $o .= '</div>';
+
+ return $o;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Search_ac.php b/Zotlabs/Module/Search_ac.php
new file mode 100644
index 000000000..78bcf374d
--- /dev/null
+++ b/Zotlabs/Module/Search_ac.php
@@ -0,0 +1,82 @@
+<?php
+namespace Zotlabs\Module;
+
+// Autocomplete for saved searches. Should probably be put in the same place as the other autocompletes
+
+class Search_ac extends \Zotlabs\Web\Controller {
+
+ function init(){
+ if(!local_channel())
+ killme();
+
+
+ $start = (x($_REQUEST,'start')?$_REQUEST['start']:0);
+ $count = (x($_REQUEST,'count')?$_REQUEST['count']:100);
+ $search = (x($_REQUEST,'search')?$_REQUEST['search']:"");
+
+ if(x($_REQUEST,'query') && strlen($_REQUEST['query'])) {
+ $search = $_REQUEST['query'];
+ }
+
+ // Priority to people searches
+
+ if ($search) {
+ $people_sql_extra = protect_sprintf(" AND `xchan_name` LIKE '%". dbesc($search) . "%' ");
+ $tag_sql_extra = protect_sprintf(" AND term LIKE '%". dbesc($search) . "%' ");
+ }
+
+
+ $r = q("SELECT `abook_id`, `xchan_name`, `xchan_photo_s`, `xchan_url`, `xchan_addr` FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d
+ $people_sql_extra
+ ORDER BY `xchan_name` ASC ",
+ intval(local_channel())
+ );
+
+ $results = array();
+ if($r) {
+ foreach($r as $g) {
+ $results[] = array(
+ "photo" => $g['xchan_photo_s'],
+ "name" => '@'.$g['xchan_name'],
+ "id" => $g['abook_id'],
+ "link" => $g['xchan_url'],
+ "label" => '',
+ "nick" => '',
+ );
+ }
+ }
+
+ $r = q("select distinct term, tid, url from term where type in ( %d, %d ) $tag_sql_extra group by term order by term asc",
+ intval(TERM_HASHTAG),
+ intval(TERM_COMMUNITYTAG)
+ );
+
+ if(count($r)) {
+ foreach($r as $g) {
+ $results[] = array(
+ "photo" => z_root() . '/images/hashtag.png',
+ "name" => '#'.$g['term'],
+ "id" => $g['tid'],
+ "link" => $g['url'],
+ "label" => '',
+ "nick" => '',
+ );
+ }
+ }
+
+ header("content-type: application/json");
+ $o = array(
+ 'start' => $start,
+ 'count' => $count,
+ 'items' => $results,
+ );
+ echo json_encode($o);
+
+ logger('search_ac: ' . print_r($x,true));
+
+ killme();
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Service_limits.php b/Zotlabs/Module/Service_limits.php
new file mode 100644
index 000000000..2a1f78054
--- /dev/null
+++ b/Zotlabs/Module/Service_limits.php
@@ -0,0 +1,28 @@
+<?php
+namespace Zotlabs\Module; /** @file */
+
+
+
+class Service_limits extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ $account = \App::get_account();
+ if($account['account_service_class']) {
+ $x = get_config('service_class',$account['account_service_class']);
+ if($x) {
+ $o = print_r($x,true);
+ return $o;
+ }
+ }
+ return t('No service class restrictions found.');
+ }
+
+
+
+}
diff --git a/Zotlabs/Module/Settings.php b/Zotlabs/Module/Settings.php
new file mode 100644
index 000000000..413648c4d
--- /dev/null
+++ b/Zotlabs/Module/Settings.php
@@ -0,0 +1,1150 @@
+<?php
+namespace Zotlabs\Module; /** @file */
+
+require_once('include/zot.php');
+
+
+class Settings extends \Zotlabs\Web\Controller {
+
+ function init() {
+ if(! local_channel())
+ return;
+
+ if($_SESSION['delegate'])
+ return;
+
+ \App::$profile_uid = local_channel();
+
+ // default is channel settings in the absence of other arguments
+
+ if(argc() == 1) {
+ // We are setting these values - don't use the argc(), argv() functions here
+ \App::$argc = 2;
+ \App::$argv[] = 'channel';
+ }
+
+
+
+ }
+
+
+ function post() {
+
+ if(! local_channel())
+ return;
+
+ if($_SESSION['delegate'])
+ return;
+
+ $channel = \App::get_channel();
+
+ logger('mod_settings: ' . print_r($_REQUEST,true));
+
+
+ if((argc() > 1) && (argv(1) === 'oauth') && x($_POST,'remove')){
+ check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
+
+ $key = $_POST['remove'];
+ q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
+ dbesc($key),
+ local_channel());
+ goaway(z_root()."/settings/oauth/");
+ return;
+ }
+
+ if((argc() > 2) && (argv(1) === 'oauth') && (argv(2) === 'edit'||(argv(2) === 'add')) && x($_POST,'submit')) {
+
+ check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
+
+ $name = ((x($_POST,'name')) ? $_POST['name'] : '');
+ $key = ((x($_POST,'key')) ? $_POST['key'] : '');
+ $secret = ((x($_POST,'secret')) ? $_POST['secret'] : '');
+ $redirect = ((x($_POST,'redirect')) ? $_POST['redirect'] : '');
+ $icon = ((x($_POST,'icon')) ? $_POST['icon'] : '');
+ $ok = true;
+ if($name == '') {
+ $ok = false;
+ notice( t('Name is required') . EOL);
+ }
+ if($key == '' || $secret == '') {
+ $ok = false;
+ notice( t('Key and Secret are required') . EOL);
+ }
+
+ if($ok) {
+ if ($_POST['submit']==t("Update")){
+ $r = q("UPDATE clients SET
+ client_id='%s',
+ pw='%s',
+ name='%s',
+ redirect_uri='%s',
+ icon='%s',
+ uid=%d
+ WHERE client_id='%s'",
+ dbesc($key),
+ dbesc($secret),
+ dbesc($name),
+ dbesc($redirect),
+ dbesc($icon),
+ intval(local_channel()),
+ dbesc($key));
+ } else {
+ $r = q("INSERT INTO clients (client_id, pw, name, redirect_uri, icon, uid)
+ VALUES ('%s','%s','%s','%s','%s',%d)",
+ dbesc($key),
+ dbesc($secret),
+ dbesc($name),
+ dbesc($redirect),
+ dbesc($icon),
+ intval(local_channel())
+ );
+ $r = q("INSERT INTO xperm (xp_client, xp_channel, xp_perm) VALUES ('%s', %d, '%s') ",
+ dbesc($key),
+ intval(local_channel()),
+ dbesc('all')
+ );
+ }
+ }
+ goaway(z_root()."/settings/oauth/");
+ return;
+ }
+
+ if((argc() > 1) && (argv(1) == 'featured')) {
+ check_form_security_token_redirectOnErr('/settings/featured', 'settings_featured');
+
+ call_hooks('feature_settings_post', $_POST);
+
+ build_sync_packet();
+ return;
+ }
+
+
+
+ if((argc() > 1) && (argv(1) === 'features')) {
+ check_form_security_token_redirectOnErr('/settings/features', 'settings_features');
+
+ // Build list of features and check which are set
+ $features = get_features();
+ $all_features = array();
+ foreach($features as $k => $v) {
+ foreach($v as $f)
+ $all_features[] = $f[0];
+ }
+ foreach($all_features as $k) {
+ if(x($_POST,"feature_$k"))
+ set_pconfig(local_channel(),'feature',$k, 1);
+ else
+ set_pconfig(local_channel(),'feature',$k, 0);
+ }
+ build_sync_packet();
+ return;
+ }
+
+ if((argc() > 1) && (argv(1) == 'display')) {
+
+ check_form_security_token_redirectOnErr('/settings/display', 'settings_display');
+
+ $theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : \App::$channel['channel_theme']);
+ $mobile_theme = ((x($_POST,'mobile_theme')) ? notags(trim($_POST['mobile_theme'])) : '');
+ $preload_images = ((x($_POST,'preload_images')) ? intval($_POST['preload_images']) : 0);
+ $user_scalable = ((x($_POST,'user_scalable')) ? intval($_POST['user_scalable']) : 0);
+ $nosmile = ((x($_POST,'nosmile')) ? intval($_POST['nosmile']) : 0);
+ $title_tosource = ((x($_POST,'title_tosource')) ? intval($_POST['title_tosource']) : 0);
+ $channel_list_mode = ((x($_POST,'channel_list_mode')) ? intval($_POST['channel_list_mode']) : 0);
+ $network_list_mode = ((x($_POST,'network_list_mode')) ? intval($_POST['network_list_mode']) : 0);
+
+ $channel_divmore_height = ((x($_POST,'channel_divmore_height')) ? intval($_POST['channel_divmore_height']) : 400);
+ if($channel_divmore_height < 50)
+ $channel_divmore_height = 50;
+ $network_divmore_height = ((x($_POST,'network_divmore_height')) ? intval($_POST['network_divmore_height']) : 400);
+ if($network_divmore_height < 50)
+ $network_divmore_height = 50;
+
+ $browser_update = ((x($_POST,'browser_update')) ? intval($_POST['browser_update']) : 0);
+ $browser_update = $browser_update * 1000;
+ if($browser_update < 10000)
+ $browser_update = 10000;
+
+ $itemspage = ((x($_POST,'itemspage')) ? intval($_POST['itemspage']) : 20);
+ if($itemspage > 100)
+ $itemspage = 100;
+
+
+ if ($mobile_theme == "---")
+ del_pconfig(local_channel(),'system','mobile_theme');
+ else {
+ set_pconfig(local_channel(),'system','mobile_theme',$mobile_theme);
+ }
+
+ set_pconfig(local_channel(),'system','preload_images',$preload_images);
+ set_pconfig(local_channel(),'system','user_scalable',$user_scalable);
+ set_pconfig(local_channel(),'system','update_interval', $browser_update);
+ set_pconfig(local_channel(),'system','itemspage', $itemspage);
+ set_pconfig(local_channel(),'system','no_smilies',1-intval($nosmile));
+ set_pconfig(local_channel(),'system','title_tosource',$title_tosource);
+ set_pconfig(local_channel(),'system','channel_list_mode', $channel_list_mode);
+ set_pconfig(local_channel(),'system','network_list_mode', $network_list_mode);
+ set_pconfig(local_channel(),'system','channel_divmore_height', $channel_divmore_height);
+ set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height);
+
+ if ($theme == \App::$channel['channel_theme']){
+ // call theme_post only if theme has not been changed
+ if( ($themeconfigfile = $this->get_theme_config_file($theme)) != null){
+ require_once($themeconfigfile);
+ theme_post($a);
+ }
+ }
+
+ $r = q("UPDATE channel SET channel_theme = '%s' WHERE channel_id = %d",
+ dbesc($theme),
+ intval(local_channel())
+ );
+
+ call_hooks('display_settings_post', $_POST);
+ build_sync_packet();
+ goaway(z_root() . '/settings/display' );
+ return; // NOTREACHED
+ }
+
+
+ if(argc() > 1 && argv(1) === 'account') {
+
+ check_form_security_token_redirectOnErr('/settings/account', 'settings_account');
+
+ call_hooks('account_settings_post', $_POST);
+ // call_hooks('settings_account', $_POST);
+
+ $errs = array();
+
+ $email = ((x($_POST,'email')) ? trim(notags($_POST['email'])) : '');
+ $account = \App::get_account();
+ if($email != $account['account_email']) {
+ if(! valid_email($email))
+ $errs[] = t('Not valid email.');
+ $adm = trim(get_config('system','admin_email'));
+ if(($adm) && (strcasecmp($email,$adm) == 0)) {
+ $errs[] = t('Protected email address. Cannot change to that email.');
+ $email = \App::$user['email'];
+ }
+ if(! $errs) {
+ $r = q("update account set account_email = '%s' where account_id = %d",
+ dbesc($email),
+ intval($account['account_id'])
+ );
+ if(! $r)
+ $errs[] = t('System failure storing new email. Please try again.');
+ }
+ }
+
+ if($errs) {
+ foreach($errs as $err)
+ notice($err . EOL);
+ $errs = array();
+ }
+
+
+ if((x($_POST,'npassword')) || (x($_POST,'confirm'))) {
+
+ $origpass = trim($_POST['origpass']);
+
+ require_once('include/auth.php');
+ if(! account_verify_password($email,$origpass)) {
+ $errs[] = t('Password verification failed.');
+ }
+
+ $newpass = trim($_POST['npassword']);
+ $confirm = trim($_POST['confirm']);
+
+ if($newpass != $confirm ) {
+ $errs[] = t('Passwords do not match. Password unchanged.');
+ }
+
+ if((! x($newpass)) || (! x($confirm))) {
+ $errs[] = t('Empty passwords are not allowed. Password unchanged.');
+ }
+
+ if(! $errs) {
+ $salt = random_string(32);
+ $password_encoded = hash('whirlpool', $salt . $newpass);
+ $r = q("update account set account_salt = '%s', account_password = '%s', account_password_changed = '%s'
+ where account_id = %d",
+ dbesc($salt),
+ dbesc($password_encoded),
+ dbesc(datetime_convert()),
+ intval(get_account_id())
+ );
+ if($r)
+ info( t('Password changed.') . EOL);
+ else
+ $errs[] = t('Password update failed. Please try again.');
+ }
+ }
+
+
+ if($errs) {
+ foreach($errs as $err)
+ notice($err . EOL);
+ }
+ goaway(z_root() . '/settings/account' );
+ }
+
+
+ check_form_security_token_redirectOnErr('/settings', 'settings');
+
+ call_hooks('settings_post', $_POST);
+
+ $set_perms = '';
+
+ $role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : '');
+ $oldrole = get_pconfig(local_channel(),'system','permissions_role');
+
+ if(($role != $oldrole) || ($role === 'custom')) {
+
+ if($role === 'custom') {
+ $hide_presence = (((x($_POST,'hide_presence')) && (intval($_POST['hide_presence']) == 1)) ? 1: 0);
+ $publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
+ $def_group = ((x($_POST,'group-selection')) ? notags(trim($_POST['group-selection'])) : '');
+ $r = q("update channel set channel_default_group = '%s' where channel_id = %d",
+ dbesc($def_group),
+ intval(local_channel())
+ );
+
+ $global_perms = get_perms();
+
+ foreach($global_perms as $k => $v) {
+ $set_perms .= ', ' . $v[0] . ' = ' . intval($_POST[$k]) . ' ';
+ }
+ $acl = new \Zotlabs\Access\AccessList($channel);
+ $acl->set_from_array($_POST);
+ $x = $acl->get();
+
+ $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s',
+ channel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d",
+ dbesc($x['allow_cid']),
+ dbesc($x['allow_gid']),
+ dbesc($x['deny_cid']),
+ dbesc($x['deny_gid']),
+ intval(local_channel())
+ );
+ }
+ else {
+ $role_permissions = get_role_perms($_POST['permissions_role']);
+ if(! $role_permissions) {
+ notice('Permissions category could not be found.');
+ return;
+ }
+ $hide_presence = 1 - (intval($role_permissions['online']));
+ if($role_permissions['default_collection']) {
+ $r = q("select hash from groups where uid = %d and name = '%s' limit 1",
+ intval(local_channel()),
+ dbesc( t('Friends') )
+ );
+ if(! $r) {
+ require_once('include/group.php');
+ group_add(local_channel(), t('Friends'));
+ group_add_member(local_channel(),t('Friends'),$channel['channel_hash']);
+ $r = q("select hash from groups where uid = %d and name = '%s' limit 1",
+ intval(local_channel()),
+ dbesc( t('Friends') )
+ );
+ }
+ if($r) {
+ q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d",
+ dbesc($r[0]['hash']),
+ dbesc('<' . $r[0]['hash'] . '>'),
+ intval(local_channel())
+ );
+ }
+ else {
+ notice( sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL);
+ return;
+ }
+ }
+ // no default collection
+ else {
+ q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '',
+ channel_deny_cid = '' where channel_id = %d",
+ intval(local_channel())
+ );
+ }
+
+ $r = q("update abook set abook_my_perms = %d where abook_channel = %d and abook_self = 1",
+ intval((array_key_exists('perms_accept',$role_permissions)) ? $role_permissions['perms_accept'] : 0),
+ intval(local_channel())
+ );
+ set_pconfig(local_channel(),'system','autoperms',(($role_permissions['perms_auto']) ? intval($role_permissions['perms_accept']) : 0));
+
+ foreach($role_permissions as $p => $v) {
+ if(strpos($p,'channel_') !== false) {
+ $set_perms .= ', ' . $p . ' = ' . intval($v) . ' ';
+ }
+ if($p === 'directory_publish') {
+ $publish = intval($v);
+ }
+ }
+ }
+
+ set_pconfig(local_channel(),'system','hide_online_status',$hide_presence);
+ set_pconfig(local_channel(),'system','permissions_role',$role);
+ }
+
+ $username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : '');
+ $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
+ $defloc = ((x($_POST,'defloc')) ? notags(trim($_POST['defloc'])) : '');
+ $openid = ((x($_POST,'openid_url')) ? notags(trim($_POST['openid_url'])) : '');
+ $maxreq = ((x($_POST,'maxreq')) ? intval($_POST['maxreq']) : 0);
+ $expire = ((x($_POST,'expire')) ? intval($_POST['expire']) : 0);
+ $evdays = ((x($_POST,'evdays')) ? intval($_POST['evdays']) : 3);
+ $photo_path = ((x($_POST,'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : '');
+ $attach_path = ((x($_POST,'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : '');
+
+ $channel_menu = ((x($_POST['channel_menu'])) ? htmlspecialchars_decode(trim($_POST['channel_menu']),ENT_QUOTES) : '');
+
+ $expire_items = ((x($_POST,'expire_items')) ? intval($_POST['expire_items']) : 0);
+ $expire_starred = ((x($_POST,'expire_starred')) ? intval($_POST['expire_starred']) : 0);
+ $expire_photos = ((x($_POST,'expire_photos'))? intval($_POST['expire_photos']) : 0);
+ $expire_network_only = ((x($_POST,'expire_network_only'))? intval($_POST['expire_network_only']) : 0);
+
+ $allow_location = (((x($_POST,'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1: 0);
+
+ $blocktags = (((x($_POST,'blocktags')) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted!
+ $unkmail = (((x($_POST,'unkmail')) && (intval($_POST['unkmail']) == 1)) ? 1: 0);
+ $cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0);
+ $suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0);
+
+ $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0);
+ $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0);
+ $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1: 0);
+ $adult = (($_POST['adult'] == 1) ? 1 : 0);
+
+ $cal_first_day = (((x($_POST,'first_day')) && (intval($_POST['first_day']) == 1)) ? 1: 0);
+
+ $channel = \App::get_channel();
+ $pageflags = $channel['channel_pageflags'];
+ $existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0);
+ if($adult != $existing_adult)
+ $pageflags = ($pageflags ^ PAGE_ADULT);
+
+
+ $notify = 0;
+
+ if(x($_POST,'notify1'))
+ $notify += intval($_POST['notify1']);
+ if(x($_POST,'notify2'))
+ $notify += intval($_POST['notify2']);
+ if(x($_POST,'notify3'))
+ $notify += intval($_POST['notify3']);
+ if(x($_POST,'notify4'))
+ $notify += intval($_POST['notify4']);
+ if(x($_POST,'notify5'))
+ $notify += intval($_POST['notify5']);
+ if(x($_POST,'notify6'))
+ $notify += intval($_POST['notify6']);
+ if(x($_POST,'notify7'))
+ $notify += intval($_POST['notify7']);
+ if(x($_POST,'notify8'))
+ $notify += intval($_POST['notify8']);
+
+
+ $vnotify = 0;
+
+ if(x($_POST,'vnotify1'))
+ $vnotify += intval($_POST['vnotify1']);
+ if(x($_POST,'vnotify2'))
+ $vnotify += intval($_POST['vnotify2']);
+ if(x($_POST,'vnotify3'))
+ $vnotify += intval($_POST['vnotify3']);
+ if(x($_POST,'vnotify4'))
+ $vnotify += intval($_POST['vnotify4']);
+ if(x($_POST,'vnotify5'))
+ $vnotify += intval($_POST['vnotify5']);
+ if(x($_POST,'vnotify6'))
+ $vnotify += intval($_POST['vnotify6']);
+ if(x($_POST,'vnotify7'))
+ $vnotify += intval($_POST['vnotify7']);
+ if(x($_POST,'vnotify8'))
+ $vnotify += intval($_POST['vnotify8']);
+ if(x($_POST,'vnotify9'))
+ $vnotify += intval($_POST['vnotify9']);
+ if(x($_POST,'vnotify10'))
+ $vnotify += intval($_POST['vnotify10']);
+ if(x($_POST,'vnotify11'))
+ $vnotify += intval($_POST['vnotify11']);
+
+ $always_show_in_notices = x($_POST,'always_show_in_notices') ? 1 : 0;
+
+ $channel = \App::get_channel();
+
+ $err = '';
+
+ $name_change = false;
+
+ if($username != $channel['channel_name']) {
+ $name_change = true;
+ require_once('include/identity.php');
+ $err = validate_channelname($username);
+ if($err) {
+ notice($err);
+ return;
+ }
+ }
+
+ if($timezone != $channel['channel_timezone']) {
+ if(strlen($timezone))
+ date_default_timezone_set($timezone);
+ }
+
+ set_pconfig(local_channel(),'system','use_browser_location',$allow_location);
+ set_pconfig(local_channel(),'system','suggestme', $suggestme);
+ set_pconfig(local_channel(),'system','post_newfriend', $post_newfriend);
+ set_pconfig(local_channel(),'system','post_joingroup', $post_joingroup);
+ set_pconfig(local_channel(),'system','post_profilechange', $post_profilechange);
+ set_pconfig(local_channel(),'system','blocktags',$blocktags);
+ set_pconfig(local_channel(),'system','channel_menu',$channel_menu);
+ set_pconfig(local_channel(),'system','vnotify',$vnotify);
+ set_pconfig(local_channel(),'system','always_show_in_notices',$always_show_in_notices);
+ set_pconfig(local_channel(),'system','evdays',$evdays);
+ set_pconfig(local_channel(),'system','photo_path',$photo_path);
+ set_pconfig(local_channel(),'system','attach_path',$attach_path);
+ set_pconfig(local_channel(),'system','cal_first_day',$cal_first_day);
+
+ $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d",
+ dbesc($username),
+ intval($pageflags),
+ dbesc($timezone),
+ dbesc($defloc),
+ intval($notify),
+ intval($unkmail),
+ intval($maxreq),
+ intval($expire),
+ intval(local_channel())
+ );
+ if($r)
+ info( t('Settings updated.') . EOL);
+
+ if(! is_null($publish)) {
+ $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d",
+ intval($publish),
+ intval(local_channel())
+ );
+ }
+
+ if($name_change) {
+ $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'",
+ dbesc($username),
+ dbesc(datetime_convert()),
+ dbesc($channel['channel_hash'])
+ );
+ $r = q("update profile set name = '%s' where uid = %d and is_default = 1",
+ dbesc($username),
+ intval($channel['channel_id'])
+ );
+ }
+
+ proc_run('php','include/directory.php',local_channel());
+
+ build_sync_packet();
+
+
+ //$_SESSION['theme'] = $theme;
+ if($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) {
+
+ // FIXME - set to un-verified, blocked and redirect to logout
+ // Why? Are we verifying people or email addresses?
+
+ }
+
+ goaway(z_root() . '/settings' );
+ return; // NOTREACHED
+ }
+
+
+
+ function get() {
+
+ $o = '';
+ nav_set_selected('settings');
+
+
+ if((! local_channel()) || ($_SESSION['delegate'])) {
+ notice( t('Permission denied.') . EOL );
+ return login();
+ }
+
+
+ $channel = \App::get_channel();
+ if($channel)
+ head_set_icon($channel['xchan_photo_s']);
+
+ $yes_no = array(t('No'),t('Yes'));
+
+ if((argc() > 1) && (argv(1) === 'oauth')) {
+
+ if((argc() > 2) && (argv(2) === 'add')) {
+ $tpl = get_markup_template("settings_oauth_edit.tpl");
+ $o .= replace_macros($tpl, array(
+ '$form_security_token' => get_form_security_token("settings_oauth"),
+ '$title' => t('Add application'),
+ '$submit' => t('Submit'),
+ '$cancel' => t('Cancel'),
+ '$name' => array('name', t('Name'), '', t('Name of application')),
+ '$key' => array('key', t('Consumer Key'), random_string(16), t('Automatically generated - change if desired. Max length 20')),
+ '$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')),
+ '$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')),
+ '$icon' => array('icon', t('Icon url'), '', t('Optional')),
+ ));
+ return $o;
+ }
+
+ if((argc() > 3) && (argv(2) === 'edit')) {
+ $r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d",
+ dbesc(argv(3)),
+ local_channel());
+
+ if (!count($r)){
+ notice(t('Application not found.'));
+ return;
+ }
+ $app = $r[0];
+
+ $tpl = get_markup_template("settings_oauth_edit.tpl");
+ $o .= replace_macros($tpl, array(
+ '$form_security_token' => get_form_security_token("settings_oauth"),
+ '$title' => t('Add application'),
+ '$submit' => t('Update'),
+ '$cancel' => t('Cancel'),
+ '$name' => array('name', t('Name'), $app['name'] , ''),
+ '$key' => array('key', t('Consumer Key'), $app['client_id'], ''),
+ '$secret' => array('secret', t('Consumer Secret'), $app['pw'], ''),
+ '$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], ''),
+ '$icon' => array('icon', t('Icon url'), $app['icon'], ''),
+ ));
+ return $o;
+ }
+
+ if((argc() > 3) && (argv(2) === 'delete')) {
+ check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't');
+
+ $r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d",
+ dbesc(argv(3)),
+ local_channel());
+ goaway(z_root()."/settings/oauth/");
+ return;
+ }
+
+
+ $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my
+ FROM clients
+ LEFT JOIN tokens ON clients.client_id=tokens.client_id
+ WHERE clients.uid IN (%d,0)",
+ local_channel(),
+ local_channel());
+
+
+ $tpl = get_markup_template("settings_oauth.tpl");
+ $o .= replace_macros($tpl, array(
+ '$form_security_token' => get_form_security_token("settings_oauth"),
+ '$baseurl' => z_root(),
+ '$title' => t('Connected Apps'),
+ '$add' => t('Add application'),
+ '$edit' => t('Edit'),
+ '$delete' => t('Delete'),
+ '$consumerkey' => t('Client key starts with'),
+ '$noname' => t('No name'),
+ '$remove' => t('Remove authorization'),
+ '$apps' => $r,
+ ));
+ return $o;
+
+ }
+ if((argc() > 1) && (argv(1) === 'featured')) {
+ $settings_addons = "";
+
+ $o = '';
+
+ $r = q("SELECT * FROM `hook` WHERE `hook` = 'feature_settings' ");
+ if(! $r)
+ $settings_addons = t('No feature settings configured');
+
+ call_hooks('feature_settings', $settings_addons);
+
+ $tpl = get_markup_template("settings_addons.tpl");
+ $o .= replace_macros($tpl, array(
+ '$form_security_token' => get_form_security_token("settings_featured"),
+ '$title' => t('Feature/Addon Settings'),
+ '$settings_addons' => $settings_addons
+ ));
+ return $o;
+ }
+
+
+ /*
+ * ACCOUNT SETTINGS
+ */
+
+
+ if((argc() > 1) && (argv(1) === 'account')) {
+ $account_settings = "";
+
+ call_hooks('account_settings', $account_settings);
+
+ $email = \App::$account['account_email'];
+
+
+ $tpl = get_markup_template("settings_account.tpl");
+ $o .= replace_macros($tpl, array(
+ '$form_security_token' => get_form_security_token("settings_account"),
+ '$title' => t('Account Settings'),
+ '$origpass' => array('origpass', t('Current Password'), ' ',''),
+ '$password1'=> array('npassword', t('Enter New Password'), '', ''),
+ '$password2'=> array('confirm', t('Confirm New Password'), '', t('Leave password fields blank unless changing')),
+ '$submit' => t('Submit'),
+ '$email' => array('email', t('Email Address:'), $email, ''),
+ '$removeme' => t('Remove Account'),
+ '$removeaccount' => t('Remove this account including all its channels'),
+ '$account_settings' => $account_settings
+ ));
+ return $o;
+ }
+
+
+
+ if((argc() > 1) && (argv(1) === 'features')) {
+ $arr = array();
+ $features = get_features();
+
+ foreach($features as $fname => $fdata) {
+ $arr[$fname] = array();
+ $arr[$fname][0] = $fdata[0];
+ foreach(array_slice($fdata,1) as $f) {
+ $arr[$fname][1][] = array('feature_' .$f[0],$f[1],((intval(feature_enabled(local_channel(),$f[0]))) ? "1" : ''),$f[2],array(t('Off'),t('On')));
+ }
+ }
+
+ $tpl = get_markup_template("settings_features.tpl");
+ $o .= replace_macros($tpl, array(
+ '$form_security_token' => get_form_security_token("settings_features"),
+ '$title' => t('Additional Features'),
+ '$features' => $arr,
+ '$submit' => t('Submit'),
+ ));
+
+ return $o;
+ }
+
+
+
+
+
+ if((argc() > 1) && (argv(1) === 'connectors')) {
+
+ $settings_connectors = "";
+
+ call_hooks('connector_settings', $settings_connectors);
+
+ $r = null;
+
+ $tpl = get_markup_template("settings_connectors.tpl");
+
+ $o .= replace_macros($tpl, array(
+ '$form_security_token' => get_form_security_token("settings_connectors"),
+ '$title' => t('Connector Settings'),
+ '$submit' => t('Submit'),
+ '$settings_connectors' => $settings_connectors
+ ));
+
+ call_hooks('display_settings', $o);
+ return $o;
+ }
+
+ /*
+ * DISPLAY SETTINGS
+ */
+
+ if((argc() > 1) && (argv(1) === 'display')) {
+ $default_theme = get_config('system','theme');
+ if(! $default_theme)
+ $default_theme = 'default';
+ $default_mobile_theme = get_config('system','mobile_theme');
+ if(! $mobile_default_theme)
+ $mobile_default_theme = 'none';
+
+ $allowed_themes_str = get_config('system','allowed_themes');
+ $allowed_themes_raw = explode(',',$allowed_themes_str);
+ $allowed_themes = array();
+ if(count($allowed_themes_raw))
+ foreach($allowed_themes_raw as $x)
+ if(strlen(trim($x)) && is_dir("view/theme/$x"))
+ $allowed_themes[] = trim($x);
+
+
+ $themes = array();
+ $files = glob('view/theme/*');
+ if($allowed_themes) {
+ foreach($allowed_themes as $th) {
+ $f = $th;
+ $is_experimental = file_exists('view/theme/' . $th . '/experimental');
+ $unsupported = file_exists('view/theme/' . $th . '/unsupported');
+ $is_mobile = file_exists('view/theme/' . $th . '/mobile');
+ $is_library = file_exists('view/theme/'. $th . '/library');
+ $mobile_themes["---"] = t("No special theme for mobile devices");
+
+ if (!$is_experimental or ($is_experimental && (get_config('experimentals','exp_themes')==1 or get_config('experimentals','exp_themes')===false))){
+ $theme_name = (($is_experimental) ? sprintf(t('%s - (Experimental)'), $f) : $f);
+ if (! $is_library) {
+ if($is_mobile) {
+ $mobile_themes[$f] = $themes[$f] = $theme_name . ' (' . t('mobile') . ')';
+ }
+ else {
+ $mobile_themes[$f] = $themes[$f] = $theme_name;
+ }
+ }
+ }
+
+ }
+ }
+ $theme_selected = (!x($_SESSION,'theme')? $default_theme : $_SESSION['theme']);
+ $mobile_theme_selected = (!x($_SESSION,'mobile_theme')? $default_mobile_theme : $_SESSION['mobile_theme']);
+
+ $preload_images = get_pconfig(local_channel(),'system','preload_images');
+ $preload_images = (($preload_images===false)? '0': $preload_images); // default if not set: 0
+
+ $user_scalable = get_pconfig(local_channel(),'system','user_scalable');
+ $user_scalable = (($user_scalable===false)? '1': $user_scalable); // default if not set: 1
+
+ $browser_update = intval(get_pconfig(local_channel(), 'system','update_interval'));
+ $browser_update = (($browser_update == 0) ? 80 : $browser_update / 1000); // default if not set: 40 seconds
+
+ $itemspage = intval(get_pconfig(local_channel(), 'system','itemspage'));
+ $itemspage = (($itemspage > 0 && $itemspage < 101) ? $itemspage : 20); // default if not set: 20 items
+
+ $nosmile = get_pconfig(local_channel(),'system','no_smilies');
+ $nosmile = (($nosmile===false)? '0': $nosmile); // default if not set: 0
+
+ $title_tosource = get_pconfig(local_channel(),'system','title_tosource');
+ $title_tosource = (($title_tosource===false)? '0': $title_tosource); // default if not set: 0
+
+ $theme_config = "";
+ if( ($themeconfigfile = $this->get_theme_config_file($theme_selected)) != null){
+ require_once($themeconfigfile);
+ $theme_config = theme_content($a);
+ }
+
+ $tpl = get_markup_template("settings_display.tpl");
+ $o = replace_macros($tpl, array(
+ '$ptitle' => t('Display Settings'),
+ '$d_tset' => t('Theme Settings'),
+ '$d_ctset' => t('Custom Theme Settings'),
+ '$d_cset' => t('Content Settings'),
+ '$form_security_token' => get_form_security_token("settings_display"),
+ '$submit' => t('Submit'),
+ '$baseurl' => z_root(),
+ '$uid' => local_channel(),
+
+ '$theme' => (($themes) ? array('theme', t('Display Theme:'), $theme_selected, '', $themes, 'preview') : false),
+ '$mobile_theme' => (($mobile_themes) ? array('mobile_theme', t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, '') : false),
+ '$preload_images' => array('preload_images', t("Preload images before rendering the page"), $preload_images, t("The subjective page load time will be longer but the page will be ready when displayed"), $yes_no),
+ '$user_scalable' => array('user_scalable', t("Enable user zoom on mobile devices"), $user_scalable, '', $yes_no),
+ '$ajaxint' => array('browser_update', t("Update browser every xx seconds"), $browser_update, t('Minimum of 10 seconds, no maximum')),
+ '$itemspage' => array('itemspage', t("Maximum number of conversations to load at any time:"), $itemspage, t('Maximum of 100 items')),
+ '$nosmile' => array('nosmile', t("Show emoticons (smilies) as images"), 1-intval($nosmile), '', $yes_no),
+ '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no),
+ '$layout_editor' => t('System Page Layout Editor - (advanced)'),
+ '$theme_config' => $theme_config,
+ '$expert' => feature_enabled(local_channel(),'expert'),
+ '$channel_list_mode' => array('channel_list_mode', t('Use blog/list mode on channel page'), get_pconfig(local_channel(),'system','channel_list_mode'), t('(comments displayed separately)'), $yes_no),
+ '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on grid page'), get_pconfig(local_channel(),'system','network_list_mode'), t('(comments displayed separately)'), $yes_no),
+ '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','channel_divmore_height')) ? get_pconfig(local_channel(),'system','channel_divmore_height') : 400), t('click to expand content exceeding this height')),
+ '$network_divmore_height' => array('network_divmore_height', t('Grid page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','network_divmore_height')) ? get_pconfig(local_channel(),'system','network_divmore_height') : 400) , t('click to expand content exceeding this height')),
+
+
+ ));
+
+ return $o;
+ }
+
+
+
+
+
+ if(argv(1) === 'channel') {
+
+ require_once('include/acl_selectors.php');
+ require_once('include/permissions.php');
+
+
+ $p = q("SELECT * FROM `profile` WHERE `is_default` = 1 AND `uid` = %d LIMIT 1",
+ intval(local_channel())
+ );
+ if(count($p))
+ $profile = $p[0];
+
+ load_pconfig(local_channel(),'expire');
+
+ $channel = \App::get_channel();
+
+
+ $global_perms = get_perms();
+
+ $permiss = array();
+
+ $perm_opts = array(
+ array( t('Nobody except yourself'), 0),
+ array( t('Only those you specifically allow'), PERMS_SPECIFIC),
+ array( t('Approved connections'), PERMS_CONTACTS),
+ array( t('Any connections'), PERMS_PENDING),
+ array( t('Anybody on this website'), PERMS_SITE),
+ array( t('Anybody in this network'), PERMS_NETWORK),
+ array( t('Anybody authenticated'), PERMS_AUTHED),
+ array( t('Anybody on the internet'), PERMS_PUBLIC)
+ );
+
+
+ foreach($global_perms as $k => $perm) {
+ $options = array();
+ foreach($perm_opts as $opt) {
+ if((! $perm[2]) && $opt[1] == PERMS_PUBLIC)
+ continue;
+ $options[$opt[1]] = $opt[0];
+ }
+ $permiss[] = array($k,$perm[3],$channel[$perm[0]],$perm[4],$options);
+ }
+
+
+ // logger('permiss: ' . print_r($permiss,true));
+
+
+
+ $username = $channel['channel_name'];
+ $nickname = $channel['channel_address'];
+ $timezone = $channel['channel_timezone'];
+ $notify = $channel['channel_notifyflags'];
+ $defloc = $channel['channel_location'];
+
+ $maxreq = $channel['channel_max_friend_req'];
+ $expire = $channel['channel_expire_days'];
+ $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT);
+ $sys_expire = get_config('system','default_expire_days');
+
+ // $unkmail = \App::$user['unkmail'];
+ // $cntunkmail = \App::$user['cntunkmail'];
+
+ $hide_presence = intval(get_pconfig(local_channel(), 'system','hide_online_status'));
+
+
+ $expire_items = get_pconfig(local_channel(), 'expire','items');
+ $expire_items = (($expire_items===false)? '1' : $expire_items); // default if not set: 1
+
+ $expire_notes = get_pconfig(local_channel(), 'expire','notes');
+ $expire_notes = (($expire_notes===false)? '1' : $expire_notes); // default if not set: 1
+
+ $expire_starred = get_pconfig(local_channel(), 'expire','starred');
+ $expire_starred = (($expire_starred===false)? '1' : $expire_starred); // default if not set: 1
+
+ $expire_photos = get_pconfig(local_channel(), 'expire','photos');
+ $expire_photos = (($expire_photos===false)? '0' : $expire_photos); // default if not set: 0
+
+ $expire_network_only = get_pconfig(local_channel(), 'expire','network_only');
+ $expire_network_only = (($expire_network_only===false)? '0' : $expire_network_only); // default if not set: 0
+
+
+ $suggestme = get_pconfig(local_channel(), 'system','suggestme');
+ $suggestme = (($suggestme===false)? '0': $suggestme); // default if not set: 0
+
+ $post_newfriend = get_pconfig(local_channel(), 'system','post_newfriend');
+ $post_newfriend = (($post_newfriend===false)? '0': $post_newfriend); // default if not set: 0
+
+ $post_joingroup = get_pconfig(local_channel(), 'system','post_joingroup');
+ $post_joingroup = (($post_joingroup===false)? '0': $post_joingroup); // default if not set: 0
+
+ $post_profilechange = get_pconfig(local_channel(), 'system','post_profilechange');
+ $post_profilechange = (($post_profilechange===false)? '0': $post_profilechange); // default if not set: 0
+
+ $blocktags = get_pconfig(local_channel(),'system','blocktags');
+ $blocktags = (($blocktags===false) ? '0' : $blocktags);
+
+ $timezone = date_default_timezone_get();
+
+ $opt_tpl = get_markup_template("field_checkbox.tpl");
+ if(get_config('system','publish_all')) {
+ $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
+ }
+ else {
+ $profile_in_dir = replace_macros($opt_tpl,array(
+ '$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', $yes_no),
+ ));
+ }
+
+ $suggestme = replace_macros($opt_tpl,array(
+ '$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', $yes_no),
+
+ ));
+
+ $subdir = ((strlen(\App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
+
+ $tpl_addr = get_markup_template("settings_nick_set.tpl");
+
+ $prof_addr = replace_macros($tpl_addr,array(
+ '$desc' => t('Your channel address is'),
+ '$nickname' => $nickname,
+ '$subdir' => $subdir,
+ '$basepath' => \App::get_hostname()
+ ));
+
+ $stpl = get_markup_template('settings.tpl');
+
+ $acl = new \Zotlabs\Access\AccessList($channel);
+ $perm_defaults = $acl->get();
+
+ require_once('include/group.php');
+ $group_select = mini_group_select(local_channel(),$channel['channel_default_group']);
+
+ require_once('include/menu.php');
+ $m1 = menu_list(local_channel());
+ $menu = false;
+ if($m1) {
+ $menu = array();
+ $current = get_pconfig(local_channel(),'system','channel_menu');
+ $menu[] = array('name' => '', 'selected' => ((! $current) ? true : false));
+ foreach($m1 as $m) {
+ $menu[] = array('name' => htmlspecialchars($m['menu_name'],ENT_COMPAT,'UTF-8'), 'selected' => (($m['menu_name'] === $current) ? ' selected="selected" ' : false));
+ }
+ }
+
+ $evdays = get_pconfig(local_channel(),'system','evdays');
+ if(! $evdays)
+ $evdays = 3;
+
+ $permissions_role = get_pconfig(local_channel(),'system','permissions_role');
+ if(! $permissions_role)
+ $permissions_role = 'custom';
+
+ $permissions_set = (($permissions_role != 'custom') ? true : false);
+
+ $vnotify = get_pconfig(local_channel(),'system','vnotify');
+ $always_show_in_notices = get_pconfig(local_channel(),'system','always_show_in_notices');
+ if($vnotify === false)
+ $vnotify = (-1);
+
+ $o .= replace_macros($stpl,array(
+ '$ptitle' => t('Channel Settings'),
+
+ '$submit' => t('Submit'),
+ '$baseurl' => z_root(),
+ '$uid' => local_channel(),
+ '$form_security_token' => get_form_security_token("settings"),
+ '$nickname_block' => $prof_addr,
+ '$h_basic' => t('Basic Settings'),
+ '$username' => array('username', t('Full Name:'), $username,''),
+ '$email' => array('email', t('Email Address:'), $email, ''),
+ '$timezone' => array('timezone_select' , t('Your Timezone:'), $timezone, '', get_timezones()),
+ '$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')),
+ '$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), '', $yes_no),
+
+ '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no),
+
+ '$h_prv' => t('Security and Privacy Settings'),
+ '$permissions_set' => $permissions_set,
+ '$server_role' => \Zotlabs\Project\System::get_server_role(),
+ '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'),
+
+ '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no),
+
+ '$lbl_pmacro' => t('Simple Privacy Settings:'),
+ '$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'),
+ '$pmacro2' => t('Typical - <em>default public, privacy when desired (similar to social network permissions but with improved privacy)</em>'),
+ '$pmacro1' => t('Private - <em>default private, never open or public</em>'),
+ '$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'),
+ '$permiss_arr' => $permiss,
+ '$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no),
+
+ '$lbl_p2macro' => t('Advanced Privacy Settings'),
+
+ '$expire' => array('expire',t('Expire other channel content after this many days'),$expire,sprintf( t('0 or blank to use the website limit. The website expires after %d days.'),intval($sys_expire))),
+ '$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']) , t('May reduce spam activity')),
+ '$permissions' => t('Default Post Permissions'),
+ '$permdesc' => t("\x28click to open/close\x29"),
+ '$aclselect' => populate_acl($perm_defaults,false),
+ '$suggestme' => $suggestme,
+ '$group_select' => $group_select,
+ '$role' => array('permissions_role' , t('Channel permissions category:'), $permissions_role, '', get_roles()),
+
+ '$profile_in_dir' => $profile_in_dir,
+ '$hide_friends' => $hide_friends,
+ '$hide_wall' => $hide_wall,
+ '$unkmail' => $unkmail,
+ '$cntunkmail' => array('cntunkmail', t('Maximum private messages per day from unknown people:'), intval($channel['channel_max_anon_mail']) ,t("Useful to reduce spamming")),
+
+
+ '$h_not' => t('Notification Settings'),
+ '$activity_options' => t('By default post a status message when:'),
+ '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no),
+ '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no),
+ '$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no),
+ '$lbl_not' => t('Send a notification email when:'),
+ '$notify1' => array('notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no),
+ '$notify2' => array('notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no),
+ '$notify3' => array('notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no),
+ '$notify4' => array('notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no),
+ '$notify5' => array('notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no),
+ '$notify6' => array('notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no),
+ '$notify7' => array('notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no),
+ '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no),
+
+
+ '$lbl_vnot' => t('Show visual notifications including:'),
+
+ '$vnotify1' => array('vnotify1', t('Unseen grid activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no),
+ '$vnotify2' => array('vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no),
+ '$vnotify3' => array('vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no),
+ '$vnotify4' => array('vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no),
+ '$vnotify5' => array('vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no),
+ '$vnotify6' => array('vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no),
+ '$vnotify7' => array('vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no),
+ '$vnotify8' => array('vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no),
+ '$vnotify9' => array('vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no),
+ '$vnotify10' => array('vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no),
+ '$vnotify11' => array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no),
+ '$always_show_in_notices' => array('always_show_in_notices', t('Also show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no),
+
+ '$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')),
+
+ '$h_advn' => t('Advanced Account/Page Type Settings'),
+ '$h_descadvn' => t('Change the behaviour of this account for special situations'),
+ '$pagetype' => $pagetype,
+ '$expert' => feature_enabled(local_channel(),'expert'),
+ '$hint' => t('Please enable expert mode (in <a href="settings/features">Settings > Additional features</a>) to adjust!'),
+ '$lbl_misc' => t('Miscellaneous Settings'),
+ '$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')),
+ '$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')),
+ '$menus' => $menu,
+ '$menu_desc' => t('Personal menu to display in your channel pages'),
+ '$removeme' => t('Remove Channel'),
+ '$removechannel' => t('Remove this channel.'),
+ '$firefoxshare' => t('Firefox Share $Projectname provider'),
+ '$cal_first_day' => array('first_day', t('Start calendar week on monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no),
+ ));
+
+ call_hooks('settings_form',$o);
+
+ $o .= '</form>' . "\r\n";
+
+ return $o;
+ }
+ }
+
+ function get_theme_config_file($theme){
+
+ $base_theme = \App::$theme_info['extends'];
+
+ if (file_exists("view/theme/$theme/php/config.php")){
+ return "view/theme/$theme/php/config.php";
+ }
+ if (file_exists("view/theme/$base_theme/php/config.php")){
+ return "view/theme/$base_theme/php/config.php";
+ }
+ return null;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php
new file mode 100644
index 000000000..3ac67e1c0
--- /dev/null
+++ b/Zotlabs/Module/Setup.php
@@ -0,0 +1,754 @@
+<?php
+namespace Zotlabs\Module;
+/**
+ * @file mod/setup.php
+ *
+ * Controller for the initial setup/installation.
+ *
+ * @todo This setup module could need some love and improvements.
+ */
+
+
+/**
+ * @brief Initialisation for the setup module.
+ *
+ * @param[in,out] App &$a
+ */
+
+class Setup extends \Zotlabs\Web\Controller {
+
+ private static $install_wizard_pass = 1;
+
+
+ function init() {
+
+ // Ensure that if somebody hasn't read the install documentation and doesn't have all
+ // the required modules or has a totally borked shared hosting provider and they can't
+ // figure out what the hell is going on - that we at least spit out an error message which
+ // we can inquire about when they write to tell us that our software doesn't work.
+
+ // The worst thing we can do at this point is throw a white screen of death and rely on
+ // them knowing about servers and php modules and logfiles enough so that we can guess
+ // at the source of the problem. As ugly as it may be, we need to throw a technically worded
+ // PHP error message in their face. Once installation is complete application errors will
+ // throw a white screen because these error messages divulge information which can
+ // potentially be useful to hackers.
+
+ error_reporting(E_ERROR | E_WARNING | E_PARSE );
+ ini_set('log_errors', '0');
+ ini_set('display_errors', '1');
+
+ // $baseurl/setup/testrwrite to test if rewite in .htaccess is working
+ if (argc() == 2 && argv(1) == "testrewrite") {
+ echo 'ok';
+ killme();
+ }
+
+ if (x($_POST, 'pass'))
+ $this->install_wizard_pass = intval($_POST['pass']);
+ else
+ $this->install_wizard_pass = 1;
+
+ }
+
+ /**
+ * @brief Handle the actions of the different setup steps.
+ *
+ * @param[in,out] App &$a
+ */
+ function post() {
+ global $db;
+
+ switch($this->install_wizard_pass) {
+ case 1:
+ case 2:
+ return;
+ break; // just in case return don't return :)
+ case 3:
+ $urlpath = \App::get_path();
+ $dbhost = trim($_POST['dbhost']);
+ $dbport = intval(trim($_POST['dbport']));
+ $dbuser = trim($_POST['dbuser']);
+ $dbpass = trim($_POST['dbpass']);
+ $dbdata = trim($_POST['dbdata']);
+ $dbtype = intval(trim($_POST['dbtype']));
+ $phpath = trim($_POST['phpath']);
+ $adminmail = trim($_POST['adminmail']);
+ $siteurl = trim($_POST['siteurl']);
+ $advanced = ((intval($_POST['advanced'])) ? 1 : 0);
+
+ // $siteurl should not have a trailing slash
+
+ $siteurl = rtrim($siteurl,'/');
+
+ require_once('include/dba/dba_driver.php');
+ unset($db);
+ $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true);
+
+ if(! $db->connected) {
+ echo 'Database Connect failed: ' . $db->error;
+ killme();
+ \App::$data['db_conn_failed']=true;
+ }
+ /*if(get_db_errno()) {
+ unset($db);
+ $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, '', true);
+
+ if(! get_db_errno()) {
+ $r = q("CREATE DATABASE '%s'",
+ dbesc($dbdata)
+ );
+ if($r) {
+ unset($db);
+ $db = new dba($dbhost, $dbport, $dbuser, $dbpass, $dbdata, true);
+ } else {
+ \App::$data['db_create_failed']=true;
+ }
+ } else {
+ \App::$data['db_conn_failed']=true;
+ return;
+ }
+ }*/
+ //if(get_db_errno()) {
+
+ //}
+
+ return;
+ break;
+ case 4:
+ $urlpath = \App::get_path();
+ $dbhost = notags(trim($_POST['dbhost']));
+ $dbport = intval(notags(trim($_POST['dbport'])));
+ $dbuser = notags(trim($_POST['dbuser']));
+ $dbpass = notags(trim($_POST['dbpass']));
+ $dbdata = notags(trim($_POST['dbdata']));
+ $dbtype = intval(notags(trim($_POST['dbtype'])));
+ $phpath = notags(trim($_POST['phpath']));
+ $timezone = notags(trim($_POST['timezone']));
+ $adminmail = notags(trim($_POST['adminmail']));
+ $siteurl = notags(trim($_POST['siteurl']));
+ $advanced = ((intval($_POST['advanced'])) ? 1 : 0);
+
+ if($siteurl != z_root()) {
+ $test = z_fetch_url($siteurl."/setup/testrewrite");
+ if((! $test['success']) || ($test['body'] != 'ok')) {
+ \App::$data['url_fail'] = true;
+ \App::$data['url_error'] = $test['error'];
+ return;
+ }
+ }
+
+ // connect to db
+ $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true);
+
+ if(! $db->connected) {
+ echo 'CRITICAL: DB not connected.';
+ killme();
+ }
+
+ $tpl = get_intltext_template('htconfig.tpl');
+ $txt = replace_macros($tpl,array(
+ '$dbhost' => $dbhost,
+ '$dbport' => $dbport,
+ '$dbuser' => $dbuser,
+ '$dbpass' => $dbpass,
+ '$dbdata' => $dbdata,
+ '$dbtype' => $dbtype,
+ '$uno' => 1 - $advanced,
+ '$timezone' => $timezone,
+ '$siteurl' => $siteurl,
+ '$site_id' => random_string(),
+ '$phpath' => $phpath,
+ '$adminmail' => $adminmail
+ ));
+
+ $result = file_put_contents('.htconfig.php', $txt);
+ if(! $result) {
+ \App::$data['txt'] = $txt;
+ }
+
+ $errors = $this->load_database($db);
+
+ if($errors)
+ \App::$data['db_failed'] = $errors;
+ else
+ \App::$data['db_installed'] = true;
+
+ return;
+ break;
+ }
+ }
+
+ function get_db_errno() {
+ if(class_exists('mysqli'))
+ return mysqli_connect_errno();
+ else
+ return mysql_errno();
+ }
+
+ /**
+ * @brief Get output for the setup page.
+ *
+ * Depending on the state we are currently in it returns different content.
+ *
+ * @param App &$a
+ * @return string parsed HTML output
+ */
+ function get() {
+ global $db;
+
+ $o = '';
+ $wizard_status = '';
+ $install_title = t('$Projectname Server - Setup');
+
+ if(x(\App::$data, 'db_conn_failed')) {
+ $this->install_wizard_pass = 2;
+ $wizard_status = t('Could not connect to database.');
+ }
+ if(x(\App::$data, 'url_fail')) {
+ $this->install_wizard_pass = 3;
+ $wizard_status = t('Could not connect to specified site URL. Possible SSL certificate or DNS issue.');
+ if(\App::$data['url_error'])
+ $wizard_status .= ' ' . \App::$data['url_error'];
+ }
+
+ if(x(\App::$data, 'db_create_failed')) {
+ $this->install_wizard_pass = 2;
+ $wizard_status = t('Could not create table.');
+ }
+ $db_return_text = '';
+ if(x(\App::$data, 'db_installed')) {
+ $txt = '<p style="font-size: 130%;">';
+ $txt .= t('Your site database has been installed.') . EOL;
+ $db_return_text .= $txt;
+ }
+ if(x(\App::$data, 'db_failed')) {
+ $txt = t('You may need to import the file "install/schema_xxx.sql" manually using a database client.') . EOL;
+ $txt .= t('Please see the file "install/INSTALL.txt".') . EOL ."<hr>" ;
+ $txt .= "<pre>".\App::$data['db_failed'] . "</pre>". EOL ;
+ $db_return_text .= $txt;
+ }
+ if($db && $db->connected) {
+ $r = q("SELECT COUNT(*) as `total` FROM `account`");
+ if($r && count($r) && $r[0]['total']) {
+ $tpl = get_markup_template('install.tpl');
+ return replace_macros($tpl, array(
+ '$title' => $install_title,
+ '$pass' => '',
+ '$status' => t('Permission denied.'),
+ '$text' => '',
+ ));
+ }
+ }
+
+ if(x(\App::$data, 'txt') && strlen(\App::$data['txt'])) {
+ $db_return_text .= $this->manual_config($a);
+ }
+
+ if ($db_return_text != "") {
+ $tpl = get_markup_template('install.tpl');
+ return replace_macros($tpl, array(
+ '$title' => $install_title,
+ '$pass' => '',
+ '$text' => $db_return_text . $this->what_next(),
+ ));
+ }
+
+ switch ($this->install_wizard_pass){
+ case 1: { // System check
+
+ $checks = array();
+
+ $this->check_funcs($checks);
+
+ $this->check_htconfig($checks);
+
+ $this->check_store($checks);
+
+ $this->check_smarty3($checks);
+
+ $this->check_keys($checks);
+
+ if (x($_POST, 'phpath'))
+ $phpath = notags(trim($_POST['phpath']));
+
+ $this->check_php($phpath, $checks);
+
+ $this->check_phpconfig($checks);
+
+ $this->check_htaccess($checks);
+
+ $checkspassed = array_reduce($checks, "self::check_passed", true);
+
+ $tpl = get_markup_template('install_checks.tpl');
+ $o .= replace_macros($tpl, array(
+ '$title' => $install_title,
+ '$pass' => t('System check'),
+ '$checks' => $checks,
+ '$passed' => $checkspassed,
+ '$see_install' => t('Please see the file "install/INSTALL.txt".'),
+ '$next' => t('Next'),
+ '$reload' => t('Check again'),
+ '$phpath' => $phpath,
+ '$baseurl' => z_root(),
+ ));
+ return $o;
+ }; break;
+
+ case 2: { // Database config
+
+ $dbhost = ((x($_POST,'dbhost')) ? notags(trim($_POST['dbhost'])) : '127.0.0.1');
+ $dbuser = notags(trim($_POST['dbuser']));
+ $dbport = intval(notags(trim($_POST['dbport'])));
+ $dbpass = notags(trim($_POST['dbpass']));
+ $dbdata = notags(trim($_POST['dbdata']));
+ $dbtype = intval(notags(trim($_POST['dbtype'])));
+ $phpath = notags(trim($_POST['phpath']));
+ $adminmail = notags(trim($_POST['adminmail']));
+ $siteurl = notags(trim($_POST['siteurl']));
+
+ $tpl = get_markup_template('install_db.tpl');
+ $o .= replace_macros($tpl, array(
+ '$title' => $install_title,
+ '$pass' => t('Database connection'),
+ '$info_01' => t('In order to install $Projectname we need to know how to connect to your database.'),
+ '$info_02' => t('Please contact your hosting provider or site administrator if you have questions about these settings.'),
+ '$info_03' => t('The database you specify below should already exist. If it does not, please create it before continuing.'),
+
+ '$status' => $wizard_status,
+
+ '$dbhost' => array('dbhost', t('Database Server Name'), $dbhost, t('Default is 127.0.0.1')),
+ '$dbport' => array('dbport', t('Database Port'), $dbport, t('Communication port number - use 0 for default')),
+ '$dbuser' => array('dbuser', t('Database Login Name'), $dbuser, ''),
+ '$dbpass' => array('dbpass', t('Database Login Password'), $dbpass, ''),
+ '$dbdata' => array('dbdata', t('Database Name'), $dbdata, ''),
+ '$dbtype' => array('dbtype', t('Database Type'), $dbtype, '', array( 0=>'MySQL', 1=>'PostgreSQL' )),
+
+ '$adminmail' => array('adminmail', t('Site administrator email address'), $adminmail, t('Your account email address must match this in order to use the web admin panel.')),
+ '$siteurl' => array('siteurl', t('Website URL'), z_root(), t('Please use SSL (https) URL if available.')),
+ '$lbl_10' => t('Please select a default timezone for your website'),
+
+ '$baseurl' => z_root(),
+
+ '$phpath' => $phpath,
+
+ '$submit' => t('Submit'),
+ ));
+ return $o;
+ }; break;
+ case 3: { // Site settings
+ require_once('include/datetime.php');
+ $dbhost = ((x($_POST,'dbhost')) ? notags(trim($_POST['dbhost'])) : '127.0.0.1');
+ $dbport = intval(notags(trim($_POST['dbuser'])));
+ $dbuser = notags(trim($_POST['dbuser']));
+ $dbpass = notags(trim($_POST['dbpass']));
+ $dbdata = notags(trim($_POST['dbdata']));
+ $dbtype = intval(notags(trim($_POST['dbtype'])));
+ $phpath = notags(trim($_POST['phpath']));
+
+ $adminmail = notags(trim($_POST['adminmail']));
+ $siteurl = notags(trim($_POST['siteurl']));
+ $timezone = ((x($_POST,'timezone')) ? ($_POST['timezone']) : 'America/Los_Angeles');
+
+ $tpl = get_markup_template('install_settings.tpl');
+ $o .= replace_macros($tpl, array(
+ '$title' => $install_title,
+ '$pass' => t('Site settings'),
+ '$status' => $wizard_status,
+
+ '$dbhost' => $dbhost,
+ '$dbport' => $dbport,
+ '$dbuser' => $dbuser,
+ '$dbpass' => $dbpass,
+ '$dbdata' => $dbdata,
+ '$phpath' => $phpath,
+ '$dbtype' => $dbtype,
+
+ '$adminmail' => array('adminmail', t('Site administrator email address'), $adminmail, t('Your account email address must match this in order to use the web admin panel.')),
+
+ '$siteurl' => array('siteurl', t('Website URL'), z_root(), t('Please use SSL (https) URL if available.')),
+ '$advanced' => array('advanced', t('Enable $Projectname <strong>advanced</strong> features?'), 1, t('Some advanced features, while useful - may be best suited for technically proficient audiences')),
+
+ '$timezone' => array('timezone', t('Please select a default timezone for your website'), $timezone, '', get_timezones()),
+
+ '$baseurl' => z_root(),
+
+ '$submit' => t('Submit'),
+ ));
+ return $o;
+ }; break;
+ }
+ }
+
+ /**
+ * @brief Add a check result to the array for output.
+ *
+ * @param[in,out] array &$checks array passed to template
+ * @param string $title a title for the check
+ * @param boolean $status
+ * @param boolean $required
+ * @param[optional] string $help optional help string
+ */
+ function check_add(&$checks, $title, $status, $required, $help = '') {
+ $checks[] = array(
+ 'title' => $title,
+ 'status' => $status,
+ 'required' => $required,
+ 'help' => $help
+ );
+ }
+
+ /**
+ * @brief Checks the PHP environment.
+ *
+ * @param[in,out] string &$phpath
+ * @param[out] array &$checks
+ */
+ function check_php(&$phpath, &$checks) {
+ $help = '';
+
+ if (strlen($phpath)) {
+ $passed = file_exists($phpath);
+ } else {
+ if(is_windows())
+ $phpath = trim(shell_exec('where php'));
+ else
+ $phpath = trim(shell_exec('which php'));
+
+ $passed = strlen($phpath);
+ }
+
+ if(!$passed) {
+ $help .= t('Could not find a command line version of PHP in the web server PATH.'). EOL;
+ $help .= t('If you don\'t have a command line version of PHP installed on server, you will not be able to run background polling via cron.') . EOL;
+ $help .= EOL . EOL ;
+ $tpl = get_markup_template('field_input.tpl');
+ $help .= replace_macros($tpl, array(
+ '$field' => array('phpath', t('PHP executable path'), $phpath, t('Enter full path to php executable. You can leave this blank to continue the installation.')),
+ ));
+ $phpath = '';
+ }
+
+ $this->check_add($checks, t('Command line PHP').($passed?" (<tt>$phpath</tt>)":""), $passed, false, $help);
+
+ if($passed) {
+ $str = autoname(8);
+ $cmd = "$phpath install/testargs.php $str";
+ $result = trim(shell_exec($cmd));
+ $passed2 = $result == $str;
+ $help = '';
+ if(!$passed2) {
+ $help .= t('The command line version of PHP on your system does not have "register_argc_argv" enabled.'). EOL;
+ $help .= t('This is required for message delivery to work.');
+ }
+
+ $this->check_add($checks, t('PHP register_argc_argv'), $passed, true, $help);
+ }
+ }
+
+ /**
+ * @brief Some PHP configuration checks.
+ *
+ * @todo Change how we display such informational text. Add more description
+ * how to change them.
+ *
+ * @param[out] array &$checks
+ */
+ function check_phpconfig(&$checks) {
+ require_once 'include/environment.php';
+
+ $help = '';
+
+ $result = getPhpiniUploadLimits();
+ $help = sprintf(t('Your max allowed total upload size is set to %s. Maximum size of one file to upload is set to %s. You are allowed to upload up to %d files at once.'),
+ userReadableSize($result['post_max_size']),
+ userReadableSize($result['max_upload_filesize']),
+ $result['max_file_uploads']
+ );
+ $help .= '<br>' . t('You can adjust these settings in the servers php.ini.');
+
+ $this->check_add($checks, t('PHP upload limits'), true, false, $help);
+ }
+
+ /**
+ * @brief Check if the openssl implementation can generate keys.
+ *
+ * @param[out] array $checks
+ */
+ function check_keys(&$checks) {
+ $help = '';
+ $res = false;
+
+ if (function_exists('openssl_pkey_new')) {
+ $res = openssl_pkey_new(array(
+ 'digest_alg' => 'sha1',
+ 'private_key_bits' => 4096,
+ 'encrypt_key' => false)
+ );
+ }
+
+ // Get private key
+
+ if (! $res) {
+ $help .= t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys'). EOL;
+ $help .= t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
+ }
+
+ $this->check_add($checks, t('Generate encryption keys'), $res, true, $help);
+ }
+
+ /**
+ * @brief Check for some PHP functions and modules.
+ *
+ * @param[in,out] array &$checks
+ */
+ function check_funcs(&$checks) {
+ $ck_funcs = array();
+
+ // add check metadata, the real check is done bit later and return values set
+ $this->check_add($ck_funcs, t('libCurl PHP module'), true, true);
+ $this->check_add($ck_funcs, t('GD graphics PHP module'), true, true);
+ $this->check_add($ck_funcs, t('OpenSSL PHP module'), true, true);
+ $this->check_add($ck_funcs, t('mysqli or postgres PHP module'), true, true);
+ $this->check_add($ck_funcs, t('mb_string PHP module'), true, true);
+ $this->check_add($ck_funcs, t('mcrypt PHP module'), true, true);
+ $this->check_add($ck_funcs, t('xml PHP module'), true, true);
+
+ if(function_exists('apache_get_modules')){
+ if (! in_array('mod_rewrite', apache_get_modules())) {
+ $this->check_add($ck_funcs, t('Apache mod_rewrite module'), false, true, t('Error: Apache webserver mod-rewrite module is required but not installed.'));
+ } else {
+ $this->check_add($ck_funcs, t('Apache mod_rewrite module'), true, true);
+ }
+ }
+ if((! function_exists('proc_open')) || strstr(ini_get('disable_functions'),'proc_open')) {
+ $this->check_add($ck_funcs, t('proc_open'), false, true, t('Error: proc_open is required but is either not installed or has been disabled in php.ini'));
+ }
+ else {
+ $this->check_add($ck_funcs, t('proc_open'), true, true);
+ }
+
+ if(! function_exists('curl_init')) {
+ $ck_funcs[0]['status'] = false;
+ $ck_funcs[0]['help'] = t('Error: libCURL PHP module required but not installed.');
+ }
+ if(! function_exists('imagecreatefromjpeg')) {
+ $ck_funcs[1]['status'] = false;
+ $ck_funcs[1]['help'] = t('Error: GD graphics PHP module with JPEG support required but not installed.');
+ }
+ if(! function_exists('openssl_public_encrypt')) {
+ $ck_funcs[2]['status'] = false;
+ $ck_funcs[2]['help'] = t('Error: openssl PHP module required but not installed.');
+ }
+ if(! function_exists('mysqli_connect') && !function_exists('pg_connect')) {
+ $ck_funcs[3]['status'] = false;
+ $ck_funcs[3]['help'] = t('Error: mysqli or postgres PHP module required but neither are installed.');
+ }
+ if(! function_exists('mb_strlen')) {
+ $ck_funcs[4]['status'] = false;
+ $ck_funcs[4]['help'] = t('Error: mb_string PHP module required but not installed.');
+ }
+ if(! function_exists('mcrypt_encrypt')) {
+ $ck_funcs[5]['status'] = false;
+ $ck_funcs[5]['help'] = t('Error: mcrypt PHP module required but not installed.');
+ }
+ if(! extension_loaded('xml')) {
+ $ck_funcs[6]['status'] = false;
+ $ck_funcs[6]['help'] = t('Error: xml PHP module required for DAV but not installed.');
+ }
+
+ $checks = array_merge($checks, $ck_funcs);
+ }
+
+ /**
+ * @brief Check for .htconfig requirements.
+ *
+ * @param[out] array &$checks
+ */
+ function check_htconfig(&$checks) {
+ $status = true;
+ $help = '';
+
+ if( (file_exists('.htconfig.php') && !is_writable('.htconfig.php')) ||
+ (!file_exists('.htconfig.php') && !is_writable('.')) ) {
+ $status = false;
+ $help = t('The web installer needs to be able to create a file called ".htconfig.php" in the top folder of your web server and it is unable to do so.') .EOL;
+ $help .= t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.').EOL;
+ $help .= t('At the end of this procedure, we will give you a text to save in a file named .htconfig.php in your Red top folder.').EOL;
+ $help .= t('You can alternatively skip this procedure and perform a manual installation. Please see the file "install/INSTALL.txt" for instructions.').EOL;
+ }
+
+ $this->check_add($checks, t('.htconfig.php is writable'), $status, false, $help);
+ }
+
+ /**
+ * @brief Checks for our templating engine Smarty3 requirements.
+ *
+ * @param[out] array &$checks
+ */
+ function check_smarty3(&$checks) {
+ $status = true;
+ $help = '';
+
+ if(! is_writable(TEMPLATE_BUILD_PATH) ) {
+ $status = false;
+ $help = t('Red uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') .EOL;
+ $help .= sprintf( t('In order to store these compiled templates, the web server needs to have write access to the directory %s under the Red top level folder.'), TEMPLATE_BUILD_PATH) . EOL;
+ $help .= t('Please ensure that the user that your web server runs as (e.g. www-data) has write access to this folder.').EOL;
+ $help .= sprintf( t('Note: as a security measure, you should give the web server write access to %s only--not the template files (.tpl) that it contains.'), TEMPLATE_BUILD_PATH) . EOL;
+ }
+
+ $this->check_add($checks, sprintf( t('%s is writable'), TEMPLATE_BUILD_PATH), $status, true, $help);
+ }
+
+ /**
+ * @brief Check for store directory.
+ *
+ * @param[out] array &$checks
+ */
+ function check_store(&$checks) {
+ $status = true;
+ $help = '';
+
+ @os_mkdir(TEMPLATE_BUILD_PATH, STORAGE_DEFAULT_PERMISSIONS, true);
+
+ if(! is_writable('store')) {
+ $status = false;
+ $help = t('Red uses the store directory to save uploaded files. The web server needs to have write access to the store directory under the Red top level folder') . EOL;
+ $help .= t('Please ensure that the user that your web server runs as (e.g. www-data) has write access to this folder.').EOL;
+ }
+
+ $this->check_add($checks, t('store is writable'), $status, true, $help);
+ }
+
+ /**
+ * @brief Check URL rewrite und SSL certificate.
+ *
+ * @param[out] array &$checks
+ */
+ function check_htaccess(&$checks) {
+ $a = get_app();
+ $status = true;
+ $help = '';
+ $ssl_error = false;
+
+ $url = z_root() . '/setup/testrewrite';
+
+ if (function_exists('curl_init')){
+ $test = z_fetch_url($url);
+ if(! $test['success']) {
+ if(strstr($url,'https://')) {
+ $test = z_fetch_url($url,false,0,array('novalidate' => true));
+ if($test['success']) {
+ $ssl_error = true;
+ }
+ }
+ else {
+ $test = z_fetch_url(str_replace('http://','https://',$url),false,0,array('novalidate' => true));
+ if($test['success']) {
+ $ssl_error = true;
+ }
+ }
+
+ if($ssl_error) {
+ $help = t('SSL certificate cannot be validated. Fix certificate or disable https access to this site.') . EOL;
+ $help .= t('If you have https access to your website or allow connections to TCP port 443 (the https: port), you MUST use a browser-valid certificate. You MUST NOT use self-signed certificates!') . EOL;
+ $help .= t('This restriction is incorporated because public posts from you may for example contain references to images on your own hub.') . EOL;
+ $help .= t('If your certificate is not recognized, members of other sites (who may themselves have valid certificates) will get a warning message on their own site complaining about security issues.') . EOL;
+ $help .= t('This can cause usability issues elsewhere (not just on your own site) so we must insist on this requirement.') .EOL;
+ $help .= t('Providers are available that issue free certificates which are browser-valid.'). EOL;
+
+ $this->check_add($checks, t('SSL certificate validation'), false, true, $help);
+ }
+ }
+
+ if ((! $test['success']) || ($test['body'] != "ok")) {
+ $status = false;
+ $help = t('Url rewrite in .htaccess is not working. Check your server configuration.'.'Test: '.var_export($test,true));
+ }
+
+ $this->check_add($checks, t('Url rewrite is working'), $status, true, $help);
+ } else {
+ // cannot check modrewrite if libcurl is not installed
+ }
+ }
+
+
+ function manual_config(&$a) {
+ $data = htmlspecialchars(\App::$data['txt'], ENT_COMPAT, 'UTF-8');
+ $o = t('The database configuration file ".htconfig.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.');
+ $o .= "<textarea rows=\"24\" cols=\"80\" >$data</textarea>";
+
+ return $o;
+ }
+
+ function load_database_rem($v, $i){
+ $l = trim($i);
+ if (strlen($l)>1 && ($l[0]=="-" || ($l[0]=="/" && $l[1]=="*"))){
+ return $v;
+ } else {
+ return $v."\n".$i;
+ }
+ }
+
+
+ function load_database($db) {
+ $str = file_get_contents($db->get_install_script());
+ $arr = explode(';',$str);
+ $errors = false;
+ foreach($arr as $a) {
+ if(strlen(trim($a))) {
+ $r = @$db->q(trim($a));
+ if(! $r) {
+ $errors .= t('Errors encountered creating database tables.') . $a . EOL;
+ }
+ }
+ }
+
+ return $errors;
+ }
+
+ function what_next() {
+ $a = get_app();
+ // install the standard theme
+ set_config('system', 'allowed_themes', 'redbasic');
+
+ // Set a lenient list of ciphers if using openssl. Other ssl engines
+ // (e.g. NSS used in RedHat) require different syntax, so hopefully
+ // the default curl cipher list will work for most sites. If not,
+ // this can set via config. Many distros are now disabling RC4,
+ // but many Red sites still use it and are unable to change it.
+ // We do not use SSL for encryption, only to protect session cookies.
+ // z_fetch_url() is also used to import shared links and other content
+ // so in theory most any cipher could show up and we should do our best
+ // to make the content available rather than tell folks that there's a
+ // weird SSL error which they can't do anything about.
+
+ $x = curl_version();
+ if(stristr($x['ssl_version'],'openssl'))
+ set_config('system','curl_ssl_ciphers','ALL:!eNULL');
+
+ // Create a system channel
+ require_once ('include/identity.php');
+ create_sys_channel();
+
+ $baseurl = z_root();
+ return
+ t('<h1>What next</h1>')
+ ."<p>".t('IMPORTANT: You will need to [manually] setup a scheduled task for the poller.')
+ .t('Please see the file "install/INSTALL.txt".')
+ ."</p><p>"
+ .t("Go to your new hub <a href='$baseurl/register'>registration page</a> and register as new member. Remember to use the same email you have entered as administrator email. This will allow you to enter the site admin panel.")
+ ."</p>";
+ }
+
+
+ static private function check_passed($v, $c) {
+ if ($c['required'])
+ $v = $v && $c['status'];
+
+ return $v;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php
new file mode 100644
index 000000000..73db01657
--- /dev/null
+++ b/Zotlabs/Module/Share.php
@@ -0,0 +1,93 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/security.php');
+require_once('include/bbcode.php');
+
+
+class Share extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $post_id = ((argc() > 1) ? intval(argv(1)) : 0);
+
+ if(! $post_id)
+ killme();
+
+ if(! (local_channel() || remote_channel()))
+ killme();
+
+ $r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1",
+ intval($post_id)
+ );
+ if(! $r)
+ killme();
+ if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss'))
+ killme();
+
+ $sql_extra = item_permissions_sql($r[0]['uid']);
+
+ $r = q("select * from item where id = %d $sql_extra",
+ intval($post_id)
+ );
+ if(! $r)
+ killme();
+
+ /** @FIXME we only share bbcode */
+
+ if($r[0]['mimetype'] !== 'text/bbcode')
+ killme();
+
+ /** @FIXME eventually we want to post remotely via rpost on your home site */
+ // When that works remove this next bit:
+
+ if(! local_channel())
+ killme();
+
+ xchan_query($r);
+
+ $is_photo = (($r[0]['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
+ if($is_photo) {
+ $object = json_decode($r[0]['object'],true);
+ $photo_bb = $object['body'];
+ }
+
+ if (strpos($r[0]['body'], "[/share]") !== false) {
+ $pos = strpos($r[0]['body'], "[share");
+ $o = substr($r[0]['body'], $pos);
+ } else {
+ $o = "[share author='".urlencode($r[0]['author']['xchan_name']).
+ "' profile='".$r[0]['author']['xchan_url'] .
+ "' avatar='".$r[0]['author']['xchan_photo_s'].
+ "' link='".$r[0]['plink'].
+ "' posted='".$r[0]['created'].
+ "' message_id='".$r[0]['mid']."']";
+ if($r[0]['title'])
+ $o .= '[b]'.$r[0]['title'].'[/b]'."\r\n";
+ $o .= (($is_photo) ? $photo_bb . "\r\n" . $r[0]['body'] : $r[0]['body']);
+ $o .= "[/share]";
+ }
+
+ if(local_channel()) {
+ echo $o;
+ killme();
+ }
+
+ $observer = \App::get_observer();
+ $parsed = $observer['xchan_url'];
+ if($parsed) {
+ $post_url = $parsed['scheme'] . ':' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '')
+ . '/rpost';
+
+ /**
+ * @FIXME we were probably called from JS so we don't know the return page.
+ * In fact we won't be able to load the remote page.
+ * we might need an iframe
+ */
+
+ $x = z_post_url($post_url, array('f' => '', 'body' => $o ));
+ killme();
+ }
+ }
+
+}
diff --git a/Zotlabs/Module/Sharedwithme.php b/Zotlabs/Module/Sharedwithme.php
new file mode 100644
index 000000000..8eaa47dba
--- /dev/null
+++ b/Zotlabs/Module/Sharedwithme.php
@@ -0,0 +1,113 @@
+<?php
+namespace Zotlabs\Module;
+require_once('include/conversation.php');
+require_once('include/text.php');
+
+
+class Sharedwithme extends \Zotlabs\Web\Controller {
+
+ function get() {
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ $channel = \App::get_channel();
+
+ $is_owner = (local_channel() && (local_channel() == $channel['channel_id']));
+
+ //check for updated items and remove them
+ require_once('include/sharedwithme.php');
+ apply_updates();
+
+ //drop single file - localuser
+ if((argc() > 2) && (argv(2) === 'drop')) {
+
+ $id = intval(argv(1));
+
+ q("DELETE FROM item WHERE id = %d AND uid = %d",
+ intval($id),
+ intval(local_channel())
+ );
+
+ goaway(z_root() . '/sharedwithme');
+ }
+
+ //drop all files - localuser
+ if((argc() > 1) && (argv(1) === 'dropall')) {
+
+ q("DELETE FROM item WHERE verb = '%s' AND obj_type = '%s' AND uid = %d",
+ dbesc(ACTIVITY_POST),
+ dbesc(ACTIVITY_OBJ_FILE),
+ intval(local_channel())
+ );
+
+ goaway(z_root() . '/sharedwithme');
+ }
+
+ //list files
+ $r = q("SELECT id, uid, object, item_unseen FROM item WHERE verb = '%s' AND obj_type = '%s' AND uid = %d AND owner_xchan != '%s'",
+ dbesc(ACTIVITY_POST),
+ dbesc(ACTIVITY_OBJ_FILE),
+ intval(local_channel()),
+ dbesc($channel['channel_hash'])
+ );
+
+ $items =array();
+ $ids = '';
+
+ if($r) {
+
+ foreach($r as $rr) {
+ $object = json_decode($rr['object'],true);
+
+ $item = array();
+ $item['id'] = $rr['id'];
+ $item['objfiletype'] = $object['filetype'];
+ $item['objfiletypeclass'] = getIconFromType($object['filetype']);
+ $item['objurl'] = rawurldecode(get_rel_link($object['link'],'alternate')) . '?f=&zid=' . $channel['xchan_addr'];
+ $item['objfilename'] = $object['filename'];
+ $item['objfilesize'] = userReadableSize($object['filesize']);
+ $item['objedited'] = $object['edited'];
+ $item['unseen'] = $rr['item_unseen'];
+
+ $items[] = $item;
+
+ if($item['unseen'] > 0) {
+ $ids .= " '" . $rr['id'] . "',";
+ }
+
+ }
+
+ }
+
+ if($ids) {
+
+ //remove trailing ,
+ $ids = rtrim($ids, ",");
+
+ q("UPDATE item SET item_unseen = 0 WHERE id IN ( $ids ) AND uid = %d",
+ intval(local_channel())
+ );
+
+ }
+
+ $o = profile_tabs($a, $is_owner, $channel['channel_address']);
+
+ $o .= replace_macros(get_markup_template('sharedwithme.tpl'), array(
+ '$header' => t('Files: shared with me'),
+ '$name' => t('Name'),
+ '$label_new' => t('NEW'),
+ '$size' => t('Size'),
+ '$lastmod' => t('Last Modified'),
+ '$dropall' => t('Remove all files'),
+ '$drop' => t('Remove this file'),
+ '$items' => $items
+ ));
+
+ return $o;
+
+ }
+
+
+}
diff --git a/Zotlabs/Module/Siteinfo.php b/Zotlabs/Module/Siteinfo.php
new file mode 100644
index 000000000..ccca6ab43
--- /dev/null
+++ b/Zotlabs/Module/Siteinfo.php
@@ -0,0 +1,94 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Siteinfo extends \Zotlabs\Web\Controller {
+
+ function init() {
+ if (argv(1) === 'json') {
+ $data = get_site_info();
+ json_return_and_die($data);
+ }
+ }
+
+
+
+ function get() {
+
+ if(! get_config('system','hidden_version_siteinfo')) {
+ $version = sprintf( t('Version %s'), \Zotlabs\Project\System::get_project_version());
+ if(@is_dir('.git') && function_exists('shell_exec')) {
+ $commit = @shell_exec('git log -1 --format="%h"');
+ $tag = \Zotlabs\Project\System::get_std_version(); // @shell_exec('git describe --tags --abbrev=0');
+ }
+ if(! isset($commit) || strlen($commit) > 16)
+ $commit = '';
+ }
+ else {
+ $version = $commit = '';
+ }
+ $visible_plugins = array();
+ if(is_array(\App::$plugins) && count(\App::$plugins)) {
+ $r = q("select * from addon where hidden = 0");
+ if(count($r))
+ foreach($r as $rr)
+ $visible_plugins[] = $rr['name'];
+ }
+
+ $plugins_list = '';
+ if(count($visible_plugins)) {
+ $plugins_text = t('Installed plugins/addons/apps:');
+ $sorted = $visible_plugins;
+ $s = '';
+ sort($sorted);
+ foreach($sorted as $p) {
+ if(strlen($p)) {
+ if(strlen($s)) $s .= ', ';
+ $s .= $p;
+ }
+ }
+ $plugins_list .= $s;
+ }
+ else
+ $plugins_text = t('No installed plugins/addons/apps');
+
+ $txt = get_config('system','admininfo');
+ $admininfo = bbcode($txt);
+
+ if(file_exists('doc/site_donate.html'))
+ $donate .= file_get_contents('doc/site_donate.html');
+
+ if(function_exists('sys_getloadavg'))
+ $loadavg = sys_getloadavg();
+
+ $o = replace_macros(get_markup_template('siteinfo.tpl'), array(
+ '$title' => t('$Projectname'),
+ '$description' => t('This is a hub of $Projectname - a global cooperative network of decentralized privacy enhanced websites.'),
+ '$version' => $version,
+ '$tag_txt' => t('Tag: '),
+ '$tag' => $tag,
+ '$polled' => t('Last background fetch: '),
+ '$lastpoll' => get_poller_runtime(),
+ '$load_average' => t('Current load average: '),
+ '$loadavg_all' => $loadavg[0] . ', ' . $loadavg[1] . ', ' . $loadavg[2],
+ '$commit' => $commit,
+ '$web_location' => t('Running at web location') . ' ' . z_root(),
+ '$visit' => t('Please visit <a href="http://hubzilla.org">hubzilla.org</a> to learn more about $Projectname.'),
+ '$bug_text' => t('Bug reports and issues: please visit'),
+ '$bug_link_url' => 'https://github.com/redmatrix/hubzilla/issues',
+ '$bug_link_text' => t('$projectname issues'),
+ '$contact' => t('Suggestions, praise, etc. - please email "redmatrix" at librelist - dot com'),
+ '$donate' => $donate,
+ '$adminlabel' => t('Site Administrators'),
+ '$admininfo' => $admininfo,
+ '$plugins_text' => $plugins_text,
+ '$plugins_list' => $plugins_list
+ ));
+
+ call_hooks('about_hook', $o);
+
+ return $o;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Siteinfo_json.php b/Zotlabs/Module/Siteinfo_json.php
new file mode 100644
index 000000000..99c22610f
--- /dev/null
+++ b/Zotlabs/Module/Siteinfo_json.php
@@ -0,0 +1,14 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Siteinfo_json extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $data = get_site_info();
+ json_return_and_die($data);
+
+ }
+
+}
diff --git a/Zotlabs/Module/Sitelist.php b/Zotlabs/Module/Sitelist.php
new file mode 100644
index 000000000..e7d4187b7
--- /dev/null
+++ b/Zotlabs/Module/Sitelist.php
@@ -0,0 +1,67 @@
+<?php
+namespace Zotlabs\Module; /** @file */
+
+
+class Sitelist extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $start = (($_REQUEST['start']) ? intval($_REQUEST['start']) : 0);
+ $limit = ((intval($_REQUEST['limit'])) ? intval($_REQUEST['limit']) : 30);
+ $order = (($_REQUEST['order']) ? $_REQUEST['order'] : 'random');
+ $open = (($_REQUEST['open']) ? intval($_REQUEST['open']) : false);
+
+
+ $sql_order = " order by site_url ";
+ $rand = db_getfunc('rand');
+ if($order == 'random')
+ $sql_order = " order by $rand ";
+
+ $sql_limit = " LIMIT $limit OFFSET $start ";
+
+ $sql_extra = "";
+ if($open)
+ $sql_extra = " and site_register = " . intval(REGISTER_OPEN) . " ";
+
+ $realm = get_directory_realm();
+ if($realm == DIRECTORY_REALM) {
+ $sql_extra .= " and ( site_realm = '" . dbesc($realm) . "' or site_realm = '') ";
+ }
+ else
+ $sql_extra .= " and site_realm = '" . dbesc($realm) . "' ";
+
+ $result = array('success' => false);
+
+ $r = q("select count(site_url) as total from site where site_type = %d $sql_extra ",
+ intval(SITE_TYPE_ZOT)
+ );
+
+ if($r)
+ $result['total'] = intval($r[0]['total']);
+
+ $result['start'] = $start;
+ $result['limit'] = $limit;
+
+ $r = q("select * from site where site_type = %d $sql_extra $sql_order $sql_limit",
+ intval(SITE_TYPE_ZOT)
+ );
+
+ $result['results'] = 0;
+ $result['entries'] = array();
+
+ if($r) {
+ $result['success'] = true;
+ $result['results'] = count($r);
+
+ foreach($r as $rr) {
+ $result['entries'][] = array('url' => $rr['site_url']);
+ }
+
+ }
+
+ echo json_encode($result);
+ killme();
+
+
+ }
+}
diff --git a/Zotlabs/Module/Smilies.php b/Zotlabs/Module/Smilies.php
new file mode 100644
index 000000000..efac07f84
--- /dev/null
+++ b/Zotlabs/Module/Smilies.php
@@ -0,0 +1,21 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Smilies extends \Zotlabs\Web\Controller {
+
+ function get() {
+ if (\App::$argv[1]==="json"){
+ $tmp = list_smilies();
+ $results = array();
+ for($i = 0; $i < count($tmp['texts']); $i++) {
+ $results[] = array('text' => $tmp['texts'][$i], 'icon' => $tmp['icons'][$i]);
+ }
+ json_return_and_die($results);
+ }
+ else {
+ return smilies('',true);
+ }
+ }
+
+}
diff --git a/Zotlabs/Module/Sources.php b/Zotlabs/Module/Sources.php
new file mode 100644
index 000000000..cca9e5ebf
--- /dev/null
+++ b/Zotlabs/Module/Sources.php
@@ -0,0 +1,173 @@
+<?php
+namespace Zotlabs\Module; /** @file */
+
+
+class Sources extends \Zotlabs\Web\Controller {
+
+ function post() {
+ if(! local_channel())
+ return;
+
+ if(! feature_enabled(local_channel(),'channel_sources'))
+ return '';
+
+ $source = intval($_REQUEST['source']);
+ $xchan = $_REQUEST['xchan'];
+ $abook = intval($_REQUEST['abook']);
+ $words = $_REQUEST['words'];
+ $frequency = $_REQUEST['frequency'];
+ $name = $_REQUEST['name'];
+
+ $channel = \App::get_channel();
+
+ if($name == '*')
+ $xchan = '*';
+
+ if($abook) {
+ $r = q("select abook_xchan from abook where abook_id = %d and abook_channel = %d limit 1",
+ intval($abook),
+ intval(local_channel())
+ );
+ if($r)
+ $xchan = $r[0]['abook_xchan'];
+ }
+
+ if(! $xchan) {
+ notice ( t('Failed to create source. No channel selected.') . EOL);
+ return;
+ }
+
+ if(! $source) {
+ $r = q("insert into source ( src_channel_id, src_channel_xchan, src_xchan, src_patt )
+ values ( %d, '%s', '%s', '%s' ) ",
+ intval(local_channel()),
+ dbesc($channel['channel_hash']),
+ dbesc($xchan),
+ dbesc($words)
+ );
+ if($r) {
+ info( t('Source created.') . EOL);
+ }
+ goaway(z_root() . '/sources');
+ }
+ else {
+ $r = q("update source set src_xchan = '%s', src_patt = '%s' where src_channel_id = %d and src_id = %d",
+ dbesc($xchan),
+ dbesc($words),
+ intval(local_channel()),
+ intval($source)
+ );
+ if($r) {
+ info( t('Source updated.') . EOL);
+ }
+
+ }
+ }
+
+
+ function get() {
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ return '';
+ }
+
+ if(! feature_enabled(local_channel(),'channel_sources')) {
+ return '';
+ }
+
+ // list sources
+ if(argc() == 1) {
+ $r = q("select source.*, xchan.* from source left join xchan on src_xchan = xchan_hash where src_channel_id = %d",
+ intval(local_channel())
+ );
+ if($r) {
+ for($x = 0; $x < count($r); $x ++) {
+ if($r[$x]['src_xchan'] == '*') {
+ $r[$x]['xchan_name'] = t('*');
+ }
+ $r[$x]['src_patt'] = htmlspecialchars($r[$x]['src_patt'], ENT_COMPAT,'UTF-8');
+ }
+ }
+ $o = replace_macros(get_markup_template('sources_list.tpl'), array(
+ '$title' => t('Channel Sources'),
+ '$desc' => t('Manage remote sources of content for your channel.'),
+ '$new' => t('New Source'),
+ '$sources' => $r
+ ));
+ return $o;
+ }
+
+ if(argc() == 2 && argv(1) === 'new') {
+ // TODO add the words 'or RSS feed' and corresponding code to manage feeds and frequency
+
+ $o = replace_macros(get_markup_template('sources_new.tpl'), array(
+ '$title' => t('New Source'),
+ '$desc' => t('Import all or selected content from the following channel into this channel and distribute it according to your channel settings.'),
+ '$words' => array( 'words', t('Only import content with these words (one per line)'),'',t('Leave blank to import all public content')),
+ '$name' => array( 'name', t('Channel Name'), '', ''),
+ '$submit' => t('Submit')
+ ));
+ return $o;
+
+ }
+
+ if(argc() == 2 && intval(argv(1))) {
+ // edit source
+ $r = q("select source.*, xchan.* from source left join xchan on src_xchan = xchan_hash where src_id = %d and src_channel_id = %d limit 1",
+ intval(argv(1)),
+ intval(local_channel())
+ );
+ if($r) {
+ $x = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+ dbesc($r[0]['src_xchan']),
+ intval(local_channel())
+ );
+ }
+ if(! $r) {
+ notice( t('Source not found.') . EOL);
+ return '';
+ }
+
+ $r[0]['src_patt'] = htmlspecialchars($r[0]['src_patt'], ENT_QUOTES,'UTF-8');
+
+ $o = replace_macros(get_markup_template('sources_edit.tpl'), array(
+ '$title' => t('Edit Source'),
+ '$drop' => t('Delete Source'),
+ '$id' => $r[0]['src_id'],
+ '$desc' => t('Import all or selected content from the following channel into this channel and distribute it according to your channel settings.'),
+ '$words' => array( 'words', t('Only import content with these words (one per line)'),$r[0]['src_patt'],t('Leave blank to import all public content')),
+ '$xchan' => $r[0]['src_xchan'],
+ '$abook' => $x[0]['abook_id'],
+ '$name' => array( 'name', t('Channel Name'), $r[0]['xchan_name'], ''),
+ '$submit' => t('Submit')
+ ));
+ return $o;
+
+ }
+
+ if(argc() == 3 && intval(argv(1)) && argv(2) === 'drop') {
+ $r = q("select * from source where src_id = %d and src_channel_id = %d limit 1",
+ intval(argv(1)),
+ intval(local_channel())
+ );
+ if(! $r) {
+ notice( t('Source not found.') . EOL);
+ return '';
+ }
+ $r = q("delete from source where src_id = %d and src_channel_id = %d",
+ intval(argv(1)),
+ intval(local_channel())
+ );
+ if($r)
+ info( t('Source removed') . EOL);
+ else
+ notice( t('Unable to remove source.') . EOL);
+
+ goaway(z_root() . '/sources');
+
+ }
+
+ // shouldn't get here.
+
+ }
+}
diff --git a/Zotlabs/Module/Sslify.php b/Zotlabs/Module/Sslify.php
new file mode 100644
index 000000000..db73f85e0
--- /dev/null
+++ b/Zotlabs/Module/Sslify.php
@@ -0,0 +1,30 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Sslify extends \Zotlabs\Web\Controller {
+
+ function init() {
+ $x = z_fetch_url($_REQUEST['url']);
+ if($x['success']) {
+ $h = explode("\n",$x['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'];
+
+ header('Content-Type: ' . $type);
+ echo $x['body'];
+ killme();
+ }
+ killme();
+ // for some reason when this fallback is in place - it gets triggered
+ // often, (creating mixed content exceptions) even though there is
+ // nothing obvious missing on the page when we bypass it.
+ goaway($_REQUEST['url']);
+ }
+
+
+}
diff --git a/Zotlabs/Module/Starred.php b/Zotlabs/Module/Starred.php
new file mode 100644
index 000000000..73a2dc808
--- /dev/null
+++ b/Zotlabs/Module/Starred.php
@@ -0,0 +1,39 @@
+<?php
+namespace Zotlabs\Module;
+
+
+
+class Starred extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $starred = 0;
+
+ if(! local_channel())
+ killme();
+ if(argc() > 1)
+ $message_id = intval(argv(1));
+ if(! $message_id)
+ killme();
+
+ $r = q("SELECT item_flags FROM item WHERE uid = %d AND id = %d LIMIT 1",
+ intval(local_channel()),
+ intval($message_id)
+ );
+ if(! count($r))
+ killme();
+
+ $item_starred = (intval($r[0]['item_starred']) ? 0 : 1);
+
+ $r = q("UPDATE item SET item_starred = %d WHERE uid = %d and id = %d",
+ intval($item_starred),
+ intval(local_channel()),
+ intval($message_id)
+ );
+
+ header('Content-type: application/json');
+ echo json_encode(array('result' => $item_starred));
+ killme();
+ }
+
+}
diff --git a/Zotlabs/Module/Subthread.php b/Zotlabs/Module/Subthread.php
new file mode 100644
index 000000000..16a011a40
--- /dev/null
+++ b/Zotlabs/Module/Subthread.php
@@ -0,0 +1,169 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/security.php');
+require_once('include/bbcode.php');
+require_once('include/items.php');
+
+
+
+class Subthread extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ if((! local_channel()) && (! remote_channel())) {
+ return;
+ }
+
+ $item_id = ((argc() > 2) ? notags(trim(argv(2))) : 0);
+
+ if(argv(1) === 'sub')
+ $activity = ACTIVITY_FOLLOW;
+ elseif(argv(1) === 'unsub')
+ $activity = ACTIVITY_UNFOLLOW;
+
+
+ $r = q("SELECT parent FROM item WHERE id = '%s'",
+ dbesc($item_id)
+ );
+
+ if($r) {
+ $r = q("select * from item where id = parent and id = %d limit 1",
+ dbesc($r[0]['parent'])
+ );
+ }
+
+ if((! $item_id) || (! $r)) {
+ logger('subthread: no item ' . $item_id);
+ return;
+ }
+
+ $item = $r[0];
+
+ $owner_uid = $item['uid'];
+ $observer = \App::get_observer();
+ $ob_hash = (($observer) ? $observer['xchan_hash'] : '');
+
+ if(! perm_is_allowed($owner_uid,$ob_hash,'post_comments'))
+ return;
+
+ $sys = get_sys_channel();
+
+ $owner_uid = $item['uid'];
+ $owner_aid = $item['aid'];
+
+ // if this is a "discover" item, (item['uid'] is the sys channel),
+ // fallback to the item comment policy, which should've been
+ // respected when generating the conversation thread.
+ // Even if the activity is rejected by the item owner, it should still get attached
+ // to the local discover conversation on this site.
+
+ 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();
+
+
+
+
+ $mid = item_message_id();
+
+ $post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
+
+ $links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
+ $objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
+
+ $body = $item['body'];
+
+ $obj = json_encode(array(
+ 'type' => $objtype,
+ 'id' => $item['mid'],
+ 'parent' => (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']),
+ 'link' => $links,
+ 'title' => $item['title'],
+ 'content' => $item['body'],
+ 'created' => $item['created'],
+ 'edited' => $item['edited'],
+ 'author' => array(
+ 'name' => $item_author['xchan_name'],
+ 'address' => $item_author['xchan_addr'],
+ 'guid' => $item_author['xchan_guid'],
+ 'guid_sig' => $item_author['xchan_guid_sig'],
+ 'link' => array(
+ array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']),
+ array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])),
+ ),
+ ));
+
+ if(! intval($item['item_thread_top']))
+ $post_type = 'comment';
+
+ if($activity === ACTIVITY_FOLLOW)
+ $bodyverb = t('%1$s is following %2$s\'s %3$s');
+ if($activity === ACTIVITY_UNFOLLOW)
+ $bodyverb = t('%1$s stopped following %2$s\'s %3$s');
+
+ $arr = array();
+
+ $arr['mid'] = $mid;
+ $arr['aid'] = $owner_aid;
+ $arr['uid'] = $owner_uid;
+ $arr['parent'] = $item['id'];
+ $arr['parent_mid'] = $item['mid'];
+ $arr['thr_parent'] = $item['mid'];
+ $arr['owner_xchan'] = $thread_owner['xchan_hash'];
+ $arr['author_xchan'] = $observer['xchan_hash'];
+ $arr['item_origin'] = 1;
+ $arr['item_notshown'] = 1;
+ if(intval($item['item_wall']))
+ $arr['item_wall'] = 1;
+ else
+ $arr['item_wall'] = 0;
+
+ $ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]';
+ $alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
+ $plink = '[zrl=' . z_root() . '/display/' . $item['mid'] . ']' . $post_type . '[/zrl]';
+
+ $arr['body'] = sprintf( $bodyverb, $alink, $ulink, $plink );
+
+ $arr['verb'] = $activity;
+ $arr['obj_type'] = $objtype;
+ $arr['object'] = $obj;
+
+ $arr['allow_cid'] = $item['allow_cid'];
+ $arr['allow_gid'] = $item['allow_gid'];
+ $arr['deny_cid'] = $item['deny_cid'];
+ $arr['deny_gid'] = $item['deny_gid'];
+
+ $post = item_store($arr);
+ $post_id = $post['item_id'];
+
+ $arr['id'] = $post_id;
+
+ call_hooks('post_local_end', $arr);
+
+ killme();
+
+
+ }
+
+
+
+
+}
diff --git a/Zotlabs/Module/Suggest.php b/Zotlabs/Module/Suggest.php
new file mode 100644
index 000000000..367308d90
--- /dev/null
+++ b/Zotlabs/Module/Suggest.php
@@ -0,0 +1,72 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/socgraph.php');
+require_once('include/contact_widgets.php');
+require_once('include/widgets.php');
+
+
+
+class Suggest extends \Zotlabs\Web\Controller {
+
+ function init() {
+ if(! local_channel())
+ return;
+
+ if(x($_GET,'ignore')) {
+ q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
+ intval(local_channel()),
+ dbesc($_GET['ignore'])
+ );
+ }
+
+ }
+
+
+ function get() {
+
+ $o = '';
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ $_SESSION['return_url'] = z_root() . '/' . \App::$cmd;
+
+ $r = suggestion_query(local_channel(),get_observer_hash());
+
+ if(! $r) {
+ info( t('No suggestions available. If this is a new site, please try again in 24 hours.'));
+ return;
+ }
+
+ $arr = array();
+
+ foreach($r as $rr) {
+
+ $connlnk = z_root() . '/follow/?url=' . $rr['xchan_addr'];
+
+ $arr[] = array(
+ 'url' => chanlink_url($rr['xchan_url']),
+ 'common' => $rr['total'],
+ 'profile' => $rr['xchan_url'],
+ 'name' => $rr['xchan_name'],
+ 'photo' => $rr['xchan_photo_m'],
+ 'ignlnk' => z_root() . '/suggest?ignore=' . $rr['xchan_hash'],
+ 'conntxt' => t('Connect'),
+ 'connlnk' => $connlnk,
+ 'ignore' => t('Ignore/Hide')
+ );
+ }
+
+
+ $o = replace_macros(get_markup_template('suggest_page.tpl'),array(
+ '$title' => t('Channel Suggestions'),
+ '$entries' => $arr
+ ));
+
+ return $o;
+
+ }
+
+}
diff --git a/Zotlabs/Module/Tagger.php b/Zotlabs/Module/Tagger.php
new file mode 100644
index 000000000..879cf3dbb
--- /dev/null
+++ b/Zotlabs/Module/Tagger.php
@@ -0,0 +1,140 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/security.php');
+require_once('include/bbcode.php');
+require_once('include/items.php');
+
+
+
+class Tagger extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ if(! local_channel() && ! remote_channel()) {
+ return;
+ }
+
+ $observer_hash = get_observer_hash();
+ //strip html-tags
+ $term = notags(trim($_GET['term']));
+ //check if empty
+ if(! $term)
+ return;
+
+ $item_id = ((argc() > 1) ? notags(trim(argv(1))) : 0);
+
+ logger('tagger: tag ' . $term . ' item ' . $item_id);
+
+
+ $r = q("SELECT * FROM item left join xchan on xchan_hash = author_xchan WHERE id = '%s' and uid = %d LIMIT 1",
+ dbesc($item_id),
+ intval(local_channel())
+ );
+
+ if((! $item_id) || (! $r)) {
+ logger('tagger: no item ' . $item_id);
+ return;
+ }
+
+ $item = $r[0];
+
+ $owner_uid = $item['uid'];
+
+ switch($item['resource_type']) {
+ case 'photo':
+ $targettype = ACTIVITY_OBJ_PHOTO;
+ $post_type = t('photo');
+ break;
+ case 'event':
+ $targgettype = ACTIVITY_OBJ_EVENT;
+ $post_type = t('event');
+ break;
+ default:
+ $targettype = ACTIVITY_OBJ_NOTE;
+ $post_type = t('post');
+ if($item['mid'] != $item['parent_mid'])
+ $post_type = t('comment');
+ break;
+ }
+
+
+ $links = array(array('rel' => 'alternate','type' => 'text/html',
+ 'href' => z_root() . '/display/' . $item['mid']));
+
+ $target = json_encode(array(
+ 'type' => $targettype,
+ 'id' => $item['mid'],
+ 'link' => $links,
+ 'title' => $item['title'],
+ 'content' => $item['body'],
+ 'created' => $item['created'],
+ 'edited' => $item['edited'],
+ 'author' => array(
+ 'name' => $item['xchan_name'],
+ 'address' => $item['xchan_addr'],
+ 'guid' => $item['xchan_guid'],
+ 'guid_sig' => $item['xchan_guid_sig'],
+ 'link' => array(
+ array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item['xchan_url']),
+ array('rel' => 'photo', 'type' => $item['xchan_photo_mimetype'], 'href' => $item['xchan_photo_m'])),
+ ),
+ ));
+
+
+
+ $link = xmlify('<link rel="alternate" type="text/html" href="'
+ . z_root() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n") ;
+
+ $tagid = z_root() . '/search?tag=' . $term;
+ $objtype = ACTIVITY_OBJ_TAGTERM;
+
+ $obj = json_encode(array(
+ 'type' => $objtype,
+ 'id' => $tagid,
+ 'link' => array(array('rel' => 'alternate','type' => 'text/html', 'href' => $tagid)),
+ 'title' => $term,
+ 'content' => $term
+ ));
+
+ $bodyverb = t('%1$s tagged %2$s\'s %3$s with %4$s');
+
+ // saving here for reference
+ // also check out x22d5 and x2317 and x0d6b and x0db8 and x24d0 and xff20 !!!
+
+ $termlink = html_entity_decode('&#x22d5;') . '[zrl=' . z_root() . '/search?tag=' . urlencode($term) . ']'. $term . '[/zrl]';
+
+ $channel = \App::get_channel();
+
+ $arr = array();
+
+ $arr['owner_xchan'] = $item['owner_xchan'];
+ $arr['author_xchan'] = $channel['channel_hash'];
+
+ $arr['item_origin'] = 1;
+ $arr['item_wall'] = ((intval($item['item_wall'])) ? 1 : 0);
+
+ $ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]';
+ $alink = '[zrl=' . $item['xchan_url'] . ']' . $item['xchan_name'] . '[/zrl]';
+ $plink = '[zrl=' . $item['plink'] . ']' . $post_type . '[/zrl]';
+
+ $arr['body'] = sprintf( $bodyverb, $ulink, $alink, $plink, $termlink );
+
+ $arr['verb'] = ACTIVITY_TAG;
+ $arr['tgt_type'] = $targettype;
+ $arr['target'] = $target;
+ $arr['obj_type'] = $objtype;
+ $arr['object'] = $obj;
+ $arr['parent_mid'] = $item['mid'];
+
+ store_item_tag($item['uid'],$item['id'],TERM_OBJ_POST,TERM_COMMUNITYTAG,$term,$tagid);
+ $ret = post_activity_item($arr);
+
+ if($ret['success'])
+ proc_run('php','include/notifier.php','tag',$ret['activity']['id']);
+
+ killme();
+
+ }
+
+}
diff --git a/Zotlabs/Module/Tagrm.php b/Zotlabs/Module/Tagrm.php
new file mode 100644
index 000000000..81ae30aa5
--- /dev/null
+++ b/Zotlabs/Module/Tagrm.php
@@ -0,0 +1,147 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/bbcode.php');
+
+
+class Tagrm extends \Zotlabs\Web\Controller {
+
+ function post() {
+
+ if(! local_channel())
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+
+ if((x($_POST,'submit')) && ($_POST['submit'] === t('Cancel')))
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+ $tag = ((x($_POST,'tag')) ? trim($_POST['tag']) : '');
+ $item = ((x($_POST,'item')) ? intval($_POST['item']) : 0 );
+
+ $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+ intval($item),
+ intval(local_channel())
+ );
+
+ if(! $r)
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+ $r = fetch_post_tags($r,true);
+
+ $item = $r[0];
+ $new_tags = array();
+
+ if($item['term']) {
+ for($x = 0; $x < count($item['term']); $x ++) {
+ if($item['term'][$x]['term'] !== hex2bin($tag))
+ $new_tags[] = $item['term'][$x];
+ }
+ }
+
+ if($new_tags)
+ $item['term'] = $new_tags;
+ else
+ unset($item['term']);
+
+ item_store_update($item);
+
+ info( t('Tag removed') . EOL );
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+ // NOTREACHED
+
+ }
+
+
+
+ function get() {
+
+ if(! local_channel()) {
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+ // NOTREACHED
+ }
+
+ // remove tag on the fly if item and tag are provided
+ if((argc() == 4) && (argv(1) === 'drop') && intval(argv(2))) {
+
+ $item = intval(argv(2));
+ $tag = argv(3);
+
+ $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+ intval($item),
+ intval(local_channel())
+ );
+
+ if(! $r)
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+ $r = fetch_post_tags($r,true);
+
+ $item = $r[0];
+
+ $new_tags = array();
+
+ if($item['term']) {
+ for($x = 0; $x < count($item['term']); $x ++) {
+ if($item['term'][$x]['term'] !== hex2bin($tag))
+ $new_tags[] = $item['term'][$x];
+ }
+ }
+
+ if($new_tags)
+ $item['term'] = $new_tags;
+ else
+ unset($item['term']);
+
+ item_store_update($item);
+
+ info( t('Tag removed') . EOL );
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+ }
+
+ //if we got only the item print a list of tags to select
+ if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
+
+ $o = '';
+
+ $item = intval(argv(2));
+
+ $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+ intval($item),
+ intval(local_channel())
+ );
+
+ if(! $r)
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+ $r = fetch_post_tags($r,true);
+
+ if(! count($r[0]['term']))
+ goaway(z_root() . '/' . $_SESSION['photo_return']);
+
+ $o .= '<h3>' . t('Remove Item Tag') . '</h3>';
+
+ $o .= '<p id="tag-remove-desc">' . t('Select a tag to remove: ') . '</p>';
+
+ $o .= '<form id="tagrm" action="tagrm" method="post" >';
+ $o .= '<input type="hidden" name="item" value="' . $item . '" />';
+ $o .= '<ul>';
+
+
+ foreach($r[0]['term'] as $x) {
+ $o .= '<li><input type="checkbox" name="tag" value="' . bin2hex($x['term']) . '" >' . bbcode($x['term']) . '</input></li>';
+ }
+
+ $o .= '</ul>';
+ $o .= '<input id="tagrm-submit" type="submit" name="submit" value="' . t('Remove') .'" />';
+ $o .= '<input id="tagrm-cancel" type="submit" name="submit" value="' . t('Cancel') .'" />';
+ $o .= '</form>';
+
+ return $o;
+
+ }
+
+ }
+
+}
diff --git a/Zotlabs/Module/Tasks.php b/Zotlabs/Module/Tasks.php
new file mode 100644
index 000000000..ab05f8be9
--- /dev/null
+++ b/Zotlabs/Module/Tasks.php
@@ -0,0 +1,112 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/event.php');
+
+
+
+class Tasks extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+
+ // logger('request: ' . print_r($_REQUEST,true));
+
+ $arr = array();
+
+ if(argc() > 1 && argv(1) === 'fetch') {
+ if(argc() > 2 && argv(2) === 'all')
+ $arr['all'] = 1;
+
+ $x = tasks_fetch($arr);
+ if($x['tasks']) {
+ $x['html'] = '';
+ foreach($x['tasks'] as $y) {
+ $x['html'] .= '<div class="tasklist-item"><input type="checkbox" onchange="taskComplete(' . $y['id'] . '); return false;" /> ' . $y['summary'] . '</div>';
+ }
+ }
+ json_return_and_die($x);
+ }
+
+ }
+
+
+
+ function post() {
+
+
+ // logger('post: ' . print_r($_POST,true));
+
+
+ if(! local_channel())
+ return;
+
+ $channel = \App::get_channel();
+
+ if((argc() > 2) && (argv(1) === 'complete') && intval(argv(2))) {
+ $ret = array('success' => false);
+ $r = q("select * from event where `type` = 'task' and uid = %d and id = %d limit 1",
+ intval(local_channel()),
+ intval(argv(2))
+ );
+ if($r) {
+ $event = $r[0];
+ if($event['event_status'] === 'COMPLETED') {
+ $event['event_status'] = 'IN-PROCESS';
+ $event['event_status_date'] = NULL_DATE;
+ $event['event_percent'] = 0;
+ $event['event_sequence'] = $event['event_sequence'] + 1;
+ $event['edited'] = datetime_convert();
+ }
+ else {
+ $event['event_status'] = 'COMPLETED';
+ $event['event_status_date'] = datetime_convert();
+ $event['event_percent'] = 100;
+ $event['event_sequence'] = $event['event_sequence'] + 1;
+ $event['edited'] = datetime_convert();
+ }
+ $x = event_store_event($event);
+ if($x)
+ $ret['success'] = true;
+ }
+ json_return_and_die($ret);
+ }
+
+ if(argc() == 2 && argv(1) === 'new') {
+ $text = escape_tags(trim($_REQUEST['summary']));
+ if(! $text)
+ return array('success' => false);
+ $event = array();
+ $event['account'] = $channel['channel_account_id'];
+ $event['uid'] = $channel['channel_id'];
+ $event['event_xchan'] = $channel['channel_hash'];
+ $event['type'] = 'task';
+ $event['nofinish'] = true;
+ $event['created'] = $event['edited'] = $event['start'] = datetime_convert();
+ $event['adjust'] = 1;
+ $event['allow_cid'] = '<' . $channel['channel_hash'] . '>';
+ $event['summary'] = escape_tags($_REQUEST['summary']);
+ $x = event_store_event($event);
+ if($x)
+ $x['success'] = true;
+ else
+ $x = array('success' => false);
+ json_return_and_die($x);
+ }
+
+
+ }
+
+
+
+
+
+ function get() {
+
+ if(! local_channel())
+ return;
+
+
+ return '';
+ }
+}
diff --git a/Zotlabs/Module/Thing.php b/Zotlabs/Module/Thing.php
new file mode 100644
index 000000000..e95ec53f6
--- /dev/null
+++ b/Zotlabs/Module/Thing.php
@@ -0,0 +1,368 @@
+<?php
+namespace Zotlabs\Module;
+/**
+ * @file mod/thing.php
+ * @brief
+ */
+
+require_once('include/items.php');
+require_once('include/security.php');
+require_once('include/contact_selectors.php');
+require_once('include/acl_selectors.php');
+
+
+class Thing extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if(! local_channel())
+ return;
+
+ $channel = \App::get_channel();
+
+ $term_hash = (($_REQUEST['term_hash']) ? $_REQUEST['term_hash'] : '');
+
+ $name = escape_tags($_REQUEST['term']);
+ $verb = escape_tags($_REQUEST['verb']);
+ $activity = intval($_REQUEST['activity']);
+ $profile_guid = escape_tags($_REQUEST['profile_assign']);
+ $url = $_REQUEST['link'];
+ $photo = $_REQUEST['img'];
+
+ $hash = random_string();
+
+ $verbs = obj_verbs();
+
+ /**
+ * verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants"
+ * We use the first person form when creating an activity, but the third person for use in activities
+ * @FIXME There is no accounting for verb gender for languages where this is significant. We may eventually
+ * require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module.
+ */
+
+ $translated_verb = $verbs[$verb][1];
+
+ /*
+ * The site administrator can do things that normals cannot.
+ * This is restricted because it will likely cause
+ * an activitystreams protocol violation and the activity might
+ * choke in some other network and result in unnecessary
+ * support requests. It isn't because we're trying to be heavy-handed
+ * about what you can and can't do.
+ */
+
+ if(! $translated_verb) {
+ if(is_site_admin())
+ $translated_verb = $verb;
+ }
+
+ /*
+ * Things, objects: We do not provide definite (a, an) or indefinite (the) articles or singular/plural designators
+ * That needs to be specified in your thing. e.g. Mike has "a carrot", Greg wants "balls", Bob likes "the Boston Red Sox".
+ */
+
+ /*
+ * Future work on this module might produce more complex activities with targets, e.g. Phillip likes Karen's moustache
+ * and to describe other non-thing objects like channels, such as Karl wants Susan - where Susan represents a channel profile.
+ */
+
+ if((! $name) || (! $translated_verb))
+ return;
+
+ $acl = new \Zotlabs\Access\AccessList($channel);
+
+ if(array_key_exists('contact_allow',$_REQUEST)
+ || array_key_exists('group_allow',$_REQUEST)
+ || array_key_exists('contact_deny',$_REQUEST)
+ || array_key_exists('group_deny',$_REQUEST)) {
+ $acl->set_from_array($_REQUEST);
+ }
+
+ $x = $acl->get();
+
+ if($term_hash) {
+ $t = q("select * from obj where obj_obj = '%s' and obj_channel = %d limit 1",
+ dbesc($term_hash),
+ intval(local_channel())
+ );
+ if(! $t) {
+ notice( t('Item not found.') . EOL);
+ return;
+ }
+ $orig_record = $t[0];
+ if($photo != $orig_record['obj_imgurl']) {
+ $arr = import_xchan_photo($photo,get_observer_hash(),true);
+ $local_photo = $arr[0];
+ $local_photo_type = $arr[3];
+ }
+ else
+ $local_photo = $orig_record['obj_imgurl'];
+
+ $r = q("update obj set obj_term = '%s', obj_url = '%s', obj_imgurl = '%s', obj_edited = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where obj_obj = '%s' and obj_channel = %d ",
+ dbesc($name),
+ dbesc(($url) ? $url : z_root() . '/thing/' . $term_hash),
+ dbesc($local_photo),
+ dbesc(datetime_convert()),
+ dbesc($x['allow_cid']),
+ dbesc($x['allow_gid']),
+ dbesc($x['deny_cid']),
+ dbesc($x['deny_gid']),
+ dbesc($term_hash),
+ intval(local_channel())
+ );
+
+ info( t('Thing updated') . EOL);
+
+ $r = q("select * from obj where obj_channel = %d and obj_obj = '%s' limit 1",
+ intval(local_channel()),
+ dbesc($term_hash)
+ );
+ if($r) {
+ build_sync_packet(0, array('obj' => $r));
+ }
+
+ return;
+ }
+
+ $sql = (($profile_guid) ? " and profile_guid = '" . dbesc($profile_guid) . "' " : " and is_default = 1 ");
+ $p = q("select profile_guid, is_default from profile where uid = %d $sql limit 1",
+ intval(local_channel())
+ );
+
+ if($p)
+ $profile = $p[0];
+ else
+ return;
+
+ $local_photo = null;
+
+ if($photo) {
+ $arr = import_xchan_photo($photo,get_observer_hash(),true);
+ $local_photo = $arr[0];
+ $local_photo_type = $arr[3];
+ }
+
+ $created = datetime_convert();
+ $url = (($url) ? $url : z_root() . '/thing/' . $hash);
+
+ $r = q("insert into obj ( obj_page, obj_verb, obj_type, obj_channel, obj_obj, obj_term, obj_url, obj_imgurl, obj_created, obj_edited, allow_cid, allow_gid, deny_cid, deny_gid ) values ('%s','%s', %d, %d, '%s','%s','%s','%s','%s','%s','%s','%s','%s','%s') ",
+ dbesc($profile['profile_guid']),
+ dbesc($verb),
+ intval(TERM_OBJ_THING),
+ intval(local_channel()),
+ dbesc($hash),
+ dbesc($name),
+ dbesc($url),
+ dbesc(($photo) ? $local_photo : ''),
+ dbesc($created),
+ dbesc($created),
+ dbesc($x['allow_cid']),
+ dbesc($x['allow_gid']),
+ dbesc($x['deny_cid']),
+ dbesc($x['deny_gid'])
+ );
+
+ if(! $r) {
+ notice( t('Object store: failed'));
+ return;
+ }
+
+ info( t('Thing added'));
+
+ $r = q("select * from obj where obj_channel = %d and obj_obj = '%s' limit 1",
+ intval(local_channel()),
+ dbesc($hash)
+ );
+ if($r) {
+ build_sync_packet(0, array('obj' => $r));
+ }
+
+ if($activity) {
+ $arr = array();
+ $links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $url));
+ if($local_photo)
+ $links[] = array('rel' => 'photo', 'type' => $local_photo_type, 'href' => $local_photo);
+
+ $objtype = ACTIVITY_OBJ_THING;
+
+ $obj = json_encode(array(
+ 'type' => $objtype,
+ 'id' => $url,
+ 'link' => $links,
+ 'title' => $name,
+ 'content' => $name
+ ));
+
+ $bodyverb = str_replace('OBJ: ', '',t('OBJ: %1$s %2$s %3$s'));
+
+ $arr['owner_xchan'] = $channel['channel_hash'];
+ $arr['author_xchan'] = $channel['channel_hash'];
+
+ $arr['item_origin'] = 1;
+ $arr['item_wall'] = 1;
+ $arr['item_thread_top'] = 1;
+
+ $ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]';
+ $plink = '[zrl=' . $url . ']' . $name . '[/zrl]';
+
+ $arr['body'] = sprintf( $bodyverb, $ulink, $translated_verb, $plink );
+
+ if($local_photo)
+ $arr['body'] .= "\n\n[zmg]" . $local_photo . "[/zmg]";
+
+ $arr['verb'] = $verb;
+ $arr['obj_type'] = $objtype;
+ $arr['object'] = $obj;
+
+ if(! $profile['is_default']) {
+ $arr['item_private'] = true;
+ $str = '';
+ $r = q("select abook_xchan from abook where abook_channel = %d and abook_profile = '%s'",
+ intval(local_channel()),
+ dbesc($profile_guid)
+ );
+ if($r) {
+ $arr['allow_cid'] = '';
+ foreach($r as $rr)
+ $arr['allow_cid'] .= '<' . $rr['abook_xchan'] . '>';
+ }
+ else
+ $arr['allow_cid'] = '<' . get_observer_hash() . '>';
+ }
+
+ $ret = post_activity_item($arr);
+ }
+ }
+
+
+ function get() {
+
+ // @FIXME one problem with things is we can't share them unless we provide the channel in the url
+ // so we can definitively lookup the owner.
+
+ if(argc() == 2) {
+
+ $r = q("select obj_channel from obj where obj_type = %d and obj_obj = '%s' limit 1",
+ intval(TERM_OBJ_THING),
+ dbesc(argv(1))
+ );
+ if($r)
+ $sql_extra = permissions_sql($r[0]['obj_channel']);
+
+ $r = q("select * from obj where obj_type = %d and obj_obj = '%s' $sql_extra limit 1",
+ intval(TERM_OBJ_THING),
+ dbesc(argv(1))
+ );
+
+ if($r) {
+ return replace_macros(get_markup_template('show_thing.tpl'), array(
+ '$header' => t('Show Thing'),
+ '$edit' => t('Edit'),
+ '$delete' => t('Delete'),
+ '$canedit' => ((local_channel() && local_channel() == $r[0]['obj_channel']) ? true : false),
+ '$thing' => $r[0] ));
+ }
+ else {
+ notice( t('item not found.') . EOL);
+ return;
+ }
+ }
+
+ $channel = \App::get_channel();
+
+ if(! (local_channel() && $channel)) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ $acl = new \Zotlabs\Access\AccessList($channel);
+ $channel_acl = $acl->get();
+
+ $lockstate = (($acl->is_private()) ? 'lock' : 'unlock');
+
+ $thing_hash = '';
+
+ if(argc() == 3 && argv(1) === 'edit') {
+ $thing_hash = argv(2);
+
+ $r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1",
+ intval(TERM_OBJ_THING),
+ dbesc($thing_hash)
+ );
+
+ if((! $r) || ($r[0]['obj_channel'] != local_channel())) {
+ notice( t('Permission denied.') . EOL);
+ return '';
+ }
+
+ $o .= replace_macros(get_markup_template('thing_edit.tpl'),array(
+ '$thing_hdr' => t('Edit Thing'),
+ '$multiprof' => feature_enabled(local_channel(),'multi_profiles'),
+ '$profile_lbl' => t('Select a profile'),
+ '$profile_select' => contact_profile_assign($r[0]['obj_page']),
+ '$verb_lbl' => $channel['channel_name'],
+ '$verb_select' => obj_verb_selector($r[0]['obj_verb']),
+ '$activity' => array('activity',t('Post an activity'),true,t('Only sends to viewers of the applicable profile')),
+ '$thing_hash' => $thing_hash,
+ '$thing_lbl' => t('Name of thing e.g. something'),
+ '$thething' => $r[0]['obj_term'],
+ '$url_lbl' => t('URL of thing (optional)'),
+ '$theurl' => $r[0]['obj_url'],
+ '$img_lbl' => t('URL for photo of thing (optional)'),
+ '$imgurl' => $r[0]['obj_imgurl'],
+ '$permissions' => t('Permissions'),
+ '$aclselect' => populate_acl($channel_acl,false),
+ '$lockstate' => $lockstate,
+ '$submit' => t('Submit')
+ ));
+
+ return $o;
+ }
+
+ if(argc() == 3 && argv(1) === 'drop') {
+ $thing_hash = argv(2);
+
+ $r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1",
+ intval(TERM_OBJ_THING),
+ dbesc($thing_hash)
+ );
+
+ if((! $r) || ($r[0]['obj_channel'] != local_channel())) {
+ notice( t('Permission denied.') . EOL);
+ return '';
+ }
+
+ $x = q("delete from obj where obj_obj = '%s' and obj_type = %d and obj_channel = %d",
+ dbesc($thing_hash),
+ intval(TERM_OBJ_THING),
+ intval(local_channel())
+ );
+
+ $r[0]['obj_deleted'] = 1;
+
+ build_sync_packet(0,array('obj' => $r));
+
+ return $o;
+ }
+
+ $o .= replace_macros(get_markup_template('thing_input.tpl'),array(
+ '$thing_hdr' => t('Add Thing to your Profile'),
+ '$multiprof' => feature_enabled(local_channel(),'multi_profiles'),
+ '$profile_lbl' => t('Select a profile'),
+ '$profile_select' => contact_profile_assign(''),
+ '$verb_lbl' => $channel['channel_name'],
+ '$activity' => array('activity',t('Post an activity'),((array_key_exists('activity',$_REQUEST)) ? $_REQUEST['activity'] : true),t('Only sends to viewers of the applicable profile')),
+ '$verb_select' => obj_verb_selector(),
+ '$thing_lbl' => t('Name of thing e.g. something'),
+ '$url_lbl' => t('URL of thing (optional)'),
+ '$img_lbl' => t('URL for photo of thing (optional)'),
+ '$permissions' => t('Permissions'),
+ '$aclselect' => populate_acl($channel_acl,false),
+ '$lockstate' => $lockstate,
+ '$submit' => t('Submit')
+ ));
+
+ return $o;
+ }
+
+}
diff --git a/Zotlabs/Module/Toggle_mobile.php b/Zotlabs/Module/Toggle_mobile.php
new file mode 100644
index 000000000..9d90c0821
--- /dev/null
+++ b/Zotlabs/Module/Toggle_mobile.php
@@ -0,0 +1,23 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Toggle_mobile extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if(isset($_GET['off']))
+ $_SESSION['show_mobile'] = false;
+ else
+ $_SESSION['show_mobile'] = true;
+
+ if(isset($_GET['address']))
+ $address = $_GET['address'];
+ else
+ $address = z_root();
+
+ goaway($address);
+ }
+
+
+}
diff --git a/Zotlabs/Module/Toggle_safesearch.php b/Zotlabs/Module/Toggle_safesearch.php
new file mode 100644
index 000000000..2e9bc2575
--- /dev/null
+++ b/Zotlabs/Module/Toggle_safesearch.php
@@ -0,0 +1,31 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Toggle_safesearch extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $observer = get_observer_hash();
+ if (! $observer)
+ return;
+
+ if($observer)
+ $safe_mode = get_xconfig($observer,'directory','safe_mode');
+ if ($safe_mode == '')
+ set_xconfig($observer,'directory','safe_mode', '0');
+ elseif($safe_mode == '0')
+ set_xconfig($observer,'directory','safe_mode', '1');
+ elseif($safe_mode == '1')
+ set_xconfig($observer,'directory','safe_mode', '0');
+
+ if(isset($_GET['address']))
+ $address = $_GET['address'];
+ else
+ $address = z_root() . '/directory';
+
+ goaway($address);
+ }
+
+
+}
diff --git a/Zotlabs/Module/Uexport.php b/Zotlabs/Module/Uexport.php
new file mode 100644
index 000000000..ada7e0986
--- /dev/null
+++ b/Zotlabs/Module/Uexport.php
@@ -0,0 +1,71 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Uexport extends \Zotlabs\Web\Controller {
+
+ function init() {
+ if(! local_channel())
+ killme();
+
+ if(argc() > 1) {
+ $channel = \App::get_channel();
+
+ require_once('include/identity.php');
+
+ if(argc() > 1 && intval(argv(1)) > 1900) {
+ $year = intval(argv(1));
+ }
+
+ if(argc() > 2 && intval(argv(2)) > 0 && intval(argv(2)) <= 12) {
+ $month = intval(argv(2));
+ }
+
+ header('content-type: application/octet_stream');
+ header('content-disposition: attachment; filename="' . $channel['channel_address'] . (($year) ? '-' . $year : '') . (($month) ? '-' . $month : '') . '.json"' );
+
+ if($year) {
+ echo json_encode(identity_export_year(local_channel(),$year,$month));
+ killme();
+ }
+
+ if(argc() > 1 && argv(1) === 'basic') {
+ echo json_encode(identity_basic_export(local_channel()));
+ killme();
+ }
+
+ // FIXME - this basically doesn't work in the wild with a channel more than a few months old due to memory and execution time limits.
+ // It probably needs to be built at the CLI and offered to download as a tarball. Maybe stored in the members dav.
+
+ if(argc() > 1 && argv(1) === 'complete') {
+ echo json_encode(identity_basic_export(local_channel(),true));
+ killme();
+ }
+ }
+ }
+
+ function get() {
+
+ $y = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
+
+ $yearurl = z_root() . '/uexport/' . $y;
+ $janurl = z_root() . '/uexport/' . $y . '/1';
+ $impurl = '/import_items';
+ $o = replace_macros(get_markup_template('uexport.tpl'), array(
+ '$title' => t('Export Channel'),
+ '$basictitle' => t('Export Channel'),
+ '$basic' => t('Export your basic channel information to a file. This acts as a backup of your connections, permissions, profile and basic data, which can be used to import your data to a new server hub, but does not contain your content.'),
+ '$fulltitle' => t('Export Content'),
+ '$full' => t('Export your channel information and recent content to a JSON backup that can be restored or imported to another server hub. This backs up all of your connections, permissions, profile data and several months of posts. This file may be VERY large. Please be patient - it may take several minutes for this download to begin.'),
+ '$by_year' => t('Export your posts from a given year.'),
+
+ '$extra' => t('You may also export your posts and conversations for a particular year or month. Adjust the date in your browser location bar to select other dates. If the export fails (possibly due to memory exhaustion on your server hub), please try again selecting a more limited date range.'),
+ '$extra2' => sprintf( t('To select all posts for a given year, such as this year, visit <a href="%1$s">%2$s</a>'),$yearurl,$yearurl),
+ '$extra3' => sprintf( t('To select all posts for a given month, such as January of this year, visit <a href="%1$s">%2$s</a>'),$janurl,$janurl),
+ '$extra4' => sprintf( t('These content files may be imported or restored by visiting <a href="%1$s">%2$s</a> on any site containing your channel. For best results please import or restore these in date order (oldest first).'),$impurl,$impurl)
+
+ ));
+ return $o;
+ }
+
+}
diff --git a/mod/update_channel.php b/Zotlabs/Module/Update_channel.php
index 63a3735ea..b1b2d5103 100644
--- a/mod/update_channel.php
+++ b/Zotlabs/Module/Update_channel.php
@@ -1,5 +1,7 @@
<?php
+namespace Zotlabs\Module;
+
/**
* Module: update_profile
* Purpose: AJAX synchronisation of profile page
@@ -7,9 +9,9 @@
*/
-require_once('mod/channel.php');
+class Update_channel extends \Zotlabs\Web\Controller {
-function update_channel_content(&$a) {
+function get() {
$profile_uid = intval($_GET['p']);
$load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
@@ -33,7 +35,9 @@ function update_channel_content(&$a) {
*
*/
- $text = channel_content($a,$profile_uid,$load);
+ $mod = new Channel();
+
+ $text = $mod->get($profile_uid,$load);
$pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
$replace = "<img\${1} dst=\"\${2}\"";
@@ -62,4 +66,5 @@ function update_channel_content(&$a) {
echo "</body></html>\r\n";
killme();
+}
} \ No newline at end of file
diff --git a/Zotlabs/Module/Update_display.php b/Zotlabs/Module/Update_display.php
new file mode 100644
index 000000000..13b04204d
--- /dev/null
+++ b/Zotlabs/Module/Update_display.php
@@ -0,0 +1,48 @@
+<?php
+namespace Zotlabs\Module;
+
+// See update_profile.php for documentation
+
+require_once('include/group.php');
+
+
+class Update_display extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ $profile_uid = intval($_GET['p']);
+ if(! $profile_uid)
+ $profile_uid = (-1);
+ $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
+ header("Content-type: text/html");
+ echo "<!DOCTYPE html><html><body>\r\n";
+ echo (($_GET['msie'] == 1) ? '<div>' : '<section>');
+
+ $mod = new Display();
+ $text = $mod->get($profile_uid, $load);
+
+ $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
+ $replace = "<img\${1} dst=\"\${2}\"";
+ // $text = preg_replace($pattern, $replace, $text);
+ /*
+ if(! $load) {
+ $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
+ $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ }
+ */
+ echo str_replace("\t",' ',$text);
+ echo (($_GET['msie'] == 1) ? '</div>' : '</section>');
+ echo "</body></html>\r\n";
+ // logger('update_display: ' . $text);
+ killme();
+
+ }
+
+}
diff --git a/Zotlabs/Module/Update_home.php b/Zotlabs/Module/Update_home.php
new file mode 100644
index 000000000..0f699482e
--- /dev/null
+++ b/Zotlabs/Module/Update_home.php
@@ -0,0 +1,42 @@
+<?php
+namespace Zotlabs\Module;
+
+// See update_profile.php for documentation
+
+class Update_home extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ $profile_uid = ((intval($_GET['p'])) ? intval($_GET['p']) : (-1));
+ $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
+ header("Content-type: text/html");
+ echo "<!DOCTYPE html><html><body>\r\n";
+ echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '<div>' : '<section>');
+
+ $mod = new Home();
+ $text = $mod->get($profile_uid, $load);
+
+ $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
+ $replace = "<img\${1} dst=\"\${2}\"";
+ // $text = preg_replace($pattern, $replace, $text);
+ /*
+ if(! $load) {
+ $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
+ $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ }
+ */
+ echo str_replace("\t",' ',$text);
+ echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '</div>' : '</section>');
+ echo "</body></html>\r\n";
+ // logger('update_home: ' . $text);
+ killme();
+
+ }
+}
diff --git a/Zotlabs/Module/Update_network.php b/Zotlabs/Module/Update_network.php
new file mode 100644
index 000000000..c27b7614a
--- /dev/null
+++ b/Zotlabs/Module/Update_network.php
@@ -0,0 +1,44 @@
+<?php
+namespace Zotlabs\Module;
+
+// See update_profile.php for documentation
+
+require_once('include/group.php');
+
+class Update_network extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ $profile_uid = intval($_GET['p']);
+ $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
+ header("Content-type: text/html");
+ echo "<!DOCTYPE html><html><body>\r\n";
+ echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '<div>' : '<section>');
+
+ $mod = new Network();
+ $text = $mod->get($profile_uid, $load);
+
+ $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
+ $replace = "<img\${1} dst=\"\${2}\"";
+ // $text = preg_replace($pattern, $replace, $text);
+ /*
+ if(! $load) {
+ $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
+ $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ }
+ */
+ echo str_replace("\t",' ',$text);
+ echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '</div>' : '</section>');
+ echo "</body></html>\r\n";
+ // logger('update_network: ' . $text);
+ killme();
+
+ }
+}
diff --git a/Zotlabs/Module/Update_pubstream.php b/Zotlabs/Module/Update_pubstream.php
new file mode 100644
index 000000000..153db56ba
--- /dev/null
+++ b/Zotlabs/Module/Update_pubstream.php
@@ -0,0 +1,42 @@
+<?php
+namespace Zotlabs\Module;
+
+// See update_profile.php for documentation
+
+
+class Update_pubstream extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ $profile_uid = ((intval($_GET['p'])) ? intval($_GET['p']) : (-1));
+ $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
+ header("Content-type: text/html");
+ echo "<!DOCTYPE html><html><body>\r\n";
+ echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '<div>' : '<section>');
+
+ $mod = new Pubstream();
+ $text = $mod->get($profile_uid, $load);
+
+ $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
+ $replace = "<img\${1} dst=\"\${2}\"";
+ // $text = preg_replace($pattern, $replace, $text);
+ /*
+ if(! $load) {
+ $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
+ $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ }
+ */
+ echo str_replace("\t",' ',$text);
+ echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '</div>' : '</section>');
+ echo "</body></html>\r\n";
+ killme();
+
+ }
+}
diff --git a/Zotlabs/Module/Update_search.php b/Zotlabs/Module/Update_search.php
new file mode 100644
index 000000000..4491f40f4
--- /dev/null
+++ b/Zotlabs/Module/Update_search.php
@@ -0,0 +1,69 @@
+<?php
+namespace Zotlabs\Module;
+
+/**
+ * Module: update_profile
+ * Purpose: AJAX synchronisation of search page
+ *
+ */
+
+
+class Update_search extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ $profile_uid = intval($_GET['p']);
+ if(! $profile_uid)
+ $profile_uid = (-1);
+
+ $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
+
+ header("Content-type: text/html");
+ echo "<!DOCTYPE html><html><body>\r\n";
+
+ /**
+ * We can remove this hack once Internet Explorer recognises HTML5 natively
+ */
+
+ echo (($_GET['msie'] == 1) ? '<div>' : '<section>');
+
+ /**
+ *
+ * Grab the page inner contents by calling the content function from the profile module directly,
+ * but move any image src attributes to another attribute name. This is because
+ * some browsers will prefetch all the images for the page even if we don't need them.
+ * The only ones we need to fetch are those for new page additions, which we'll discover
+ * on the client side and then swap the image back.
+ *
+ */
+
+ $mod = new Search();
+ $text = $mod->get($profile_uid,$load);
+
+ $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
+ $replace = "<img\${1} dst=\"\${2}\"";
+ // $text = preg_replace($pattern, $replace, $text);
+ /*
+ if(! $load) {
+ $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
+ $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
+ $text = preg_replace($pattern, $replace, $text);
+ }
+ */
+ /**
+ * reportedly some versions of MSIE don't handle tabs in XMLHttpRequest documents very well
+ */
+
+ echo str_replace("\t",' ',$text);
+ echo (($_GET['msie'] == 1) ? '</div>' : '</section>');
+ echo "</body></html>\r\n";
+ killme();
+
+ }
+}
diff --git a/Zotlabs/Module/View.php b/Zotlabs/Module/View.php
new file mode 100644
index 000000000..85497a2a4
--- /dev/null
+++ b/Zotlabs/Module/View.php
@@ -0,0 +1,20 @@
+<?php
+namespace Zotlabs\Module;
+/**
+ * load view/theme/$current_theme/style.php with Hubzilla context
+ */
+
+
+class View extends \Zotlabs\Web\Controller {
+
+ function init() {
+ header("Content-Type: text/css");
+
+ $theme = argv(2);
+ $THEMEPATH = "view/theme/$theme";
+ if(file_exists("view/theme/$theme/php/style.php"))
+ require_once("view/theme/$theme/php/style.php");
+ killme();
+ }
+
+}
diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php
new file mode 100644
index 000000000..726ef043b
--- /dev/null
+++ b/Zotlabs/Module/Viewconnections.php
@@ -0,0 +1,117 @@
+<?php
+namespace Zotlabs\Module;
+require_once('include/contact_selectors.php');
+require_once('include/Contact.php');
+
+
+class Viewconnections extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
+ return;
+ }
+ if(argc() > 1)
+ profile_load($a,argv(1));
+ }
+
+ function get() {
+
+ if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
+ notice( t('Public access denied.') . EOL);
+ return;
+ }
+
+ if(((! count(\App::$profile)) || (\App::$profile['hide_friends']))) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ if(! perm_is_allowed(\App::$profile['uid'], get_observer_hash(),'view_contacts')) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ if(! $_REQUEST['aj'])
+ $_SESSION['return_url'] = \App::$query_string;
+
+
+ $is_owner = ((local_channel() && local_channel() == \App::$profile['uid']) ? true : false);
+
+ $abook_flags = " and abook_pending = 0 and abook_self = 0 ";
+ $sql_extra = '';
+
+ if(! $is_owner) {
+ $abook_flags = " and abook_hidden = 0 ";
+ $sql_extra = " and xchan_hidden = 0 ";
+ }
+
+ $r = q("SELECT count(*) as total FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra ",
+ intval(\App::$profile['uid'])
+ );
+ if($r) {
+ \App::set_pager_total($r[0]['total']);
+ }
+
+ $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra order by xchan_name LIMIT %d OFFSET %d ",
+ intval(\App::$profile['uid']),
+ intval(\App::$pager['itemspage']),
+ intval(\App::$pager['start'])
+ );
+
+ if((! $r) && (! $_REQUEST['aj'])) {
+ info( t('No connections.') . EOL );
+ return $o;
+ }
+
+ $contacts = array();
+
+ foreach($r as $rr) {
+
+ $url = chanlink_url($rr['xchan_url']);
+ if($url) {
+ $contacts[] = array(
+ 'id' => $rr['abook_id'],
+ 'archived' => (intval($rr['abook_archived']) ? true : false),
+ 'img_hover' => sprintf( t('Visit %s\'s profile [%s]'), $rr['xchan_name'], $rr['xchan_url']),
+ 'thumb' => $rr['xchan_photo_m'],
+ 'name' => substr($rr['xchan_name'],0,20),
+ 'username' => $rr['xchan_addr'],
+ 'link' => $url,
+ 'sparkle' => '',
+ 'itemurl' => $rr['url'],
+ 'network' => '',
+ );
+ }
+ }
+
+
+ if($_REQUEST['aj']) {
+ if($contacts) {
+ $o = replace_macros(get_markup_template('viewcontactsajax.tpl'),array(
+ '$contacts' => $contacts
+ ));
+ }
+ 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>";
+ $tpl = get_markup_template("viewcontact_template.tpl");
+ $o .= replace_macros($tpl, array(
+ '$title' => t('View Connections'),
+ '$contacts' => $contacts,
+ // '$paginate' => paginate($a),
+ ));
+ }
+
+ if(! $contacts)
+ $o .= '<div id="content-complete"></div>';
+
+ return $o;
+ }
+
+}
diff --git a/Zotlabs/Module/Viewsrc.php b/Zotlabs/Module/Viewsrc.php
new file mode 100644
index 000000000..63cc5e717
--- /dev/null
+++ b/Zotlabs/Module/Viewsrc.php
@@ -0,0 +1,53 @@
+<?php
+namespace Zotlabs\Module;
+
+
+
+class Viewsrc extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ $o = '';
+
+ $sys = get_sys_channel();
+
+ $item_id = ((argc() > 1) ? intval(argv(1)) : 0);
+ $json = ((argc() > 2 && argv(2) === 'json') ? true : false);
+
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ }
+
+
+ if(! $item_id) {
+ \App::$error = 404;
+ notice( t('Item not found.') . EOL);
+ }
+
+ $item_normal = item_normal();
+
+ if(local_channel() && $item_id) {
+ $r = q("select id, item_flags, item_obscured, body from item where uid in (%d , %d) and id = %d $item_normal limit 1",
+ intval(local_channel()),
+ intval($sys['channel_id']),
+ intval($item_id)
+ );
+
+ if($r) {
+ if(intval($r[0]['item_obscured']))
+ $r[0]['body'] = crypto_unencapsulate(json_decode($r[0]['body'],true),get_config('system','prvkey'));
+ $o = (($json) ? json_encode($r[0]['body']) : str_replace("\n",'<br />',$r[0]['body']));
+ }
+ }
+
+ if(is_ajax()) {
+ print '<div><i class="icon-pencil"> ' . t('Source of Item') . ' ' . $r[0]['id'] . '</i></div>';
+ echo $o;
+ killme();
+ }
+
+ return $o;
+ }
+
+
+}
diff --git a/Zotlabs/Module/Wall_attach.php b/Zotlabs/Module/Wall_attach.php
new file mode 100644
index 000000000..5bdecfa75
--- /dev/null
+++ b/Zotlabs/Module/Wall_attach.php
@@ -0,0 +1,55 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/attach.php');
+require_once('include/identity.php');
+require_once('include/photos.php');
+
+
+class Wall_attach extends \Zotlabs\Web\Controller {
+
+ function post() {
+
+ $using_api = false;
+
+ if(\App::$data['api_info'] && array_key_exists('media',$_FILES)) {
+ $using_api = true;
+ $user_info = \App::$data['api_info'];
+ $nick = $user_info['screen_name'];
+ $channel = get_channel_by_nick($user_info['screen_name']);
+ }
+ elseif(argc() > 1)
+ $channel = get_channel_by_nick(argv(1));
+
+ if(! $channel)
+ killme();
+
+ $observer = \App::get_observer();
+
+
+ $def_album = get_pconfig($channel['channel_id'],'system','photo_path');
+ $def_attach = get_pconfig($channel['channel_id'],'system','attach_path');
+
+ $r = attach_store($channel,(($observer) ? $observer['xchan_hash'] : ''),'', array('source' => 'editor', 'visible' => 0, 'album' => $def_album, 'directory' => $def_attach, 'allow_cid' => '<' . $channel['channel_hash'] . '>'));
+
+ if(! $r['success']) {
+ notice( $r['message'] . EOL);
+ killme();
+ }
+
+ if(intval($r['data']['is_photo'])) {
+ $s = "\n\n" . $r['body'] . "\n\n";
+ }
+ else {
+ $s = "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n";
+ }
+
+ if($using_api)
+ return $s;
+
+ echo $s;
+ killme();
+
+ }
+
+}
diff --git a/Zotlabs/Module/Wall_upload.php b/Zotlabs/Module/Wall_upload.php
new file mode 100644
index 000000000..fff3ed03a
--- /dev/null
+++ b/Zotlabs/Module/Wall_upload.php
@@ -0,0 +1,57 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/photo/photo_driver.php');
+require_once('include/identity.php');
+require_once('include/photos.php');
+
+
+
+
+class Wall_upload extends \Zotlabs\Web\Controller {
+
+ function post() {
+
+
+ $using_api = ((x($_FILES,'media')) ? true : false);
+
+ if($using_api) {
+ require_once('include/api.php');
+ $user_info = api_get_user($a);
+ $nick = $user_info['screen_name'];
+ }
+ else {
+ if(argc() > 1)
+ $nick = argv(1);
+ }
+
+ $channel = (($nick) ? get_channel_by_nick($nick) : false);
+
+ if(! $channel) {
+ if($using_api)
+ return;
+ notice( t('Channel not found.') . EOL);
+ killme();
+ }
+
+ $observer = \App::get_observer();
+
+ $args = array( 'source' => 'editor', 'visible' => 0, 'contact_allow' => array($channel['channel_hash']));
+
+ $ret = photo_upload($channel,$observer,$args);
+
+ if(! $ret['success']) {
+ if($using_api)
+ return;
+ notice($ret['message']);
+ killme();
+ }
+
+ if($using_api)
+ return("\n\n" . $ret['body'] . "\n\n");
+ else
+ echo "\n\n" . $ret['body'] . "\n\n";
+ killme();
+ }
+
+}
diff --git a/Zotlabs/Module/Webfinger.php b/Zotlabs/Module/Webfinger.php
new file mode 100644
index 000000000..c50680de7
--- /dev/null
+++ b/Zotlabs/Module/Webfinger.php
@@ -0,0 +1,54 @@
+<?php
+namespace Zotlabs\Module;
+
+
+
+
+class Webfinger extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+
+ $o .= '<h3>Webfinger Diagnostic</h3>';
+
+ $o .= '<form action="webfinger" method="get">';
+ $o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
+ $o .= '<input type="submit" name="submit" value="Submit" /></form>';
+
+ $o .= '<br /><br />';
+
+ $old = false;
+ if(x($_GET,'addr')) {
+ $addr = trim($_GET['addr']);
+ // if(strpos($addr,'@') !== false) {
+ $res = webfinger_rfc7033($addr,true);
+ if(! $res) {
+ $res = old_webfinger($addr);
+ $old = true;
+ }
+ // }
+ // else {
+ // if(function_exists('lrdd'))
+ // $res = lrdd($addr);
+ // }
+
+ if($res && $old) {
+ foreach($res as $r) {
+ if($r['@attributes']['rel'] === 'http://microformats.org/profile/hcard') {
+ $hcard = unamp($r['@attributes']['href']);
+ require_once('library/HTML5/Parser.php');
+ $res['vcard'] = scrape_vcard($hcard);
+ break;
+ }
+ }
+ }
+
+
+ $o .= '<pre>';
+ $o .= str_replace("\n",'<br />',print_r($res,true));
+ $o .= '</pre>';
+ }
+ return $o;
+ }
+
+}
diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php
new file mode 100644
index 000000000..84d58058e
--- /dev/null
+++ b/Zotlabs/Module/Webpages.php
@@ -0,0 +1,207 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/identity.php');
+require_once('include/conversation.php');
+require_once('include/acl_selectors.php');
+
+
+class Webpages 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;
+ }
+
+ $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype'));
+
+ if(! $mimetype) {
+ $mimetype = 'choose';
+ }
+
+ $layout = (($_REQUEST['layout']) ? $_REQUEST['layout'] : get_pconfig($owner,'system','page_layout'));
+ if(! $layout)
+ $layout = 'choose';
+
+ // 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 owner's.
+ // This lets you post pages at other people's channels.
+
+ if((! $channel) && ($uid) && ($uid == \App::$profile_uid)) {
+ $channel = \App::get_channel();
+ }
+ if($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']
+ );
+ }
+ else
+ $channel_acl = array();
+
+ $is_owner = ($uid && $uid == $owner);
+ $o = profile_tabs($a, $is_owner, \App::$profile['channel_address']);
+
+ $x = array(
+ 'webpage' => ITEM_TYPE_WEBPAGE,
+ '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' => '',
+ 'acl' => (($is_owner) ? populate_acl($channel_acl,false) : ''),
+ 'showacl' => (($is_owner) ? true : false),
+ 'visitor' => true,
+ 'profile_uid' => intval($owner),
+ 'mimetype' => $mimetype,
+ 'layout' => $layout,
+ '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);
+
+ // Get a list of webpages. We can't display all them because endless scroll makes that unusable,
+ // so just list titles and an edit link.
+
+
+ /** @TODO - this should be replaced with pagelist_widget */
+
+ $sql_extra = item_permissions_sql($owner);
+
+ $r = q("select * from item_id left join item on item_id.iid = item.id
+ where item_id.uid = %d and service = 'WEBPAGE' and item_type = %d $sql_extra order by item.created desc",
+ intval($owner),
+ intval(ITEM_TYPE_WEBPAGE)
+ );
+
+ $pages = null;
+
+ if($r) {
+ $pages = array();
+ foreach($r as $rr) {
+ unobscure($rr);
+
+ $lockstate = (($rr['allow_cid'] || $rr['allow_gid'] || $rr['deny_cid'] || $rr['deny_gid']) ? 'lock' : 'unlock');
+
+ $element_arr = array(
+ 'type' => 'webpage',
+ 'title' => $rr['title'],
+ 'body' => $rr['body'],
+ 'created' => $rr['created'],
+ 'edited' => $rr['edited'],
+ 'mimetype' => $rr['mimetype'],
+ 'pagetitle' => $rr['sid'],
+ 'mid' => $rr['mid'],
+ 'layout_mid' => $rr['layout_mid']
+ );
+ $pages[$rr['iid']][] = array(
+ 'url' => $rr['iid'],
+ 'pagetitle' => $rr['sid'],
+ 'title' => $rr['title'],
+ 'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']),
+ 'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited']),
+ 'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]',
+ 'lockstate' => $lockstate
+ );
+ }
+ }
+
+
+ //Build the base URL for edit links
+ $url = z_root() . '/editwebpage/' . $which;
+
+ $o .= replace_macros(get_markup_template('webpagelist.tpl'), array(
+ '$listtitle' => t('Webpages'),
+ '$baseurl' => $url,
+ '$create' => t('Create'),
+ '$edit' => t('Edit'),
+ '$share' => t('Share'),
+ '$delete' => t('Delete'),
+ '$pages' => $pages,
+ '$channel' => $which,
+ '$editor' => $editor,
+ '$view' => t('View'),
+ '$preview' => t('Preview'),
+ '$actions_txt' => t('Actions'),
+ '$pagelink_txt' => t('Page Link'),
+ '$title_txt' => t('Page Title'),
+ '$created_txt' => t('Created'),
+ '$edited_txt' => t('Edited')
+ ));
+
+ return $o;
+ }
+
+}
diff --git a/Zotlabs/Module/Well_known.php b/Zotlabs/Module/Well_known.php
new file mode 100644
index 000000000..b57666bff
--- /dev/null
+++ b/Zotlabs/Module/Well_known.php
@@ -0,0 +1,69 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Well_known extends \Zotlabs\Web\Controller {
+
+ function init(){
+
+ if(argc() > 1) {
+
+ $arr = array('server' => $_SERVER, 'request' => $_REQUEST);
+ call_hooks('well_known', $arr);
+
+
+ if(! check_siteallowed($_SERVER['REMOTE_ADDR'])) {
+ logger('well_known: site not allowed. ' . $_SERVER['REMOTE_ADDR']);
+ killme();
+ }
+
+ // from php.net re: REMOTE_HOST:
+ // Note: Your web server must be configured to create this variable. For example in Apache
+ // you'll need HostnameLookups On inside httpd.conf for it to exist. See also gethostbyaddr().
+
+ if(get_config('system','siteallowed_remote_host') && (! check_siteallowed($_SERVER['REMOTE_HOST']))) {
+ logger('well_known: site not allowed. ' . $_SERVER['REMOTE_HOST']);
+ killme();
+ }
+
+
+ switch(argv(1)) {
+ case 'zot-info':
+ \App::$argc -= 1;
+ array_shift(\App::$argv);
+ \App::$argv[0] = 'zfinger';
+ $module = new \Zotlabs\Module\Zfinger();
+ $module->init();
+ break;
+
+ case 'webfinger':
+ \App::$argc -= 1;
+ array_shift(\App::$argv);
+ \App::$argv[0] = 'wfinger';
+ $module = new \Zotlabs\Module\Wfinger();
+ $module->init();
+ break;
+
+ case 'host-meta':
+ \App::$argc -= 1;
+ array_shift(\App::$argv);
+ \App::$argv[0] = 'hostxrd';
+ $module = new \Zotlabs\Module\Hostxrd();
+ $module->init();
+ break;
+
+ default:
+ if(file_exists(\App::$cmd)) {
+ echo file_get_contents(\App::$cmd);
+ killme();
+ }
+ elseif(file_exists(\App::$cmd . '.php'))
+ require_once(\App::$cmd . '.php');
+ break;
+
+ }
+ }
+
+ http_status_exit(404);
+ }
+}
diff --git a/Zotlabs/Module/Wfinger.php b/Zotlabs/Module/Wfinger.php
new file mode 100644
index 000000000..fa1e11518
--- /dev/null
+++ b/Zotlabs/Module/Wfinger.php
@@ -0,0 +1,140 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/zot.php');
+
+
+class Wfinger extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $result = array();
+
+ $scheme = '';
+
+ if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS'])
+ $scheme = 'https';
+ elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443))
+ $scheme = 'https';
+
+ $zot = intval($_REQUEST['zot']);
+
+ if(($scheme !== 'https') && (! $zot)) {
+ header($_SERVER["SERVER_PROTOCOL"] . ' ' . 500 . ' ' . 'Webfinger requires HTTPS');
+ killme();
+ }
+
+
+ $resource = $_REQUEST['resource'];
+ logger('webfinger: ' . $resource,LOGGER_DEBUG);
+
+ $r = null;
+
+ if($resource) {
+
+ if(strpos($resource,'acct:') === 0) {
+ $channel = str_replace('acct:','',$resource);
+ if(strpos($channel,'@') !== false) {
+ $host = substr($channel,strpos($channel,'@')+1);
+ if(strcasecmp($host,\App::get_hostname())) {
+ goaway('https://' . $host . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=' . $zot : ''));
+ }
+ $channel = substr($channel,0,strpos($channel,'@'));
+ }
+ }
+ if(strpos($resource,'http') === 0) {
+ $channel = str_replace('~','',basename($resource));
+ }
+
+ $r = q("select * from channel left join xchan on channel_hash = xchan_hash
+ where channel_address = '%s' limit 1",
+ dbesc($channel)
+ );
+
+ }
+
+ header('Access-Control-Allow-Origin: *');
+
+
+ if($resource && $r) {
+
+ $h = q("select hubloc_addr from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
+ dbesc($r[0]['channel_hash'])
+ );
+
+ $result['subject'] = $resource;
+
+ $aliases = array(
+ z_root() . '/channel/' . $r[0]['channel_address'],
+ z_root() . '/~' . $r[0]['channel_address']
+ );
+
+ if($h) {
+ foreach($h as $hh) {
+ $aliases[] = 'acct:' . $hh['hubloc_addr'];
+ }
+ }
+
+ $result['aliases'] = array();
+
+ $result['properties'] = array(
+ 'http://webfinger.net/ns/name' => $r[0]['channel_name'],
+ 'http://xmlns.com/foaf/0.1/name' => $r[0]['channel_name']
+ );
+
+ foreach($aliases as $alias)
+ if($alias != $resource)
+ $result['aliases'][] = $alias;
+
+ $result['links'] = array(
+
+ array(
+ 'rel' => 'http://webfinger.net/rel/avatar',
+ 'type' => $r[0]['xchan_photo_mimetype'],
+ 'href' => $r[0]['xchan_photo_l']
+ ),
+
+ array(
+ 'rel' => 'http://webfinger.net/rel/profile-page',
+ 'href' => z_root() . '/profile/' . $r[0]['channel_address'],
+ ),
+
+ array(
+ 'rel' => 'http://webfinger.net/rel/blog',
+ 'href' => z_root() . '/channel/' . $r[0]['channel_address'],
+ ),
+
+ array(
+ 'rel' => 'http://ostatus.org/schema/1.0/subscribe',
+ 'template' => z_root() . '/follow/url={uri}',
+ ),
+
+ array(
+ 'rel' => 'http://purl.org/zot/protocol',
+ 'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r[0]['xchan_addr'],
+ ),
+
+ array(
+ 'rel' => 'magic-public-key',
+ 'href' => 'data:application/magic-public-key,' . salmon_key($r[0]['channel_pubkey']),
+ )
+ );
+
+ if($zot) {
+ // get a zotinfo packet and return it with webfinger
+ $result['zot'] = zotinfo(array('address' => $r[0]['xchan_addr']));
+ }
+ }
+ else {
+ header($_SERVER["SERVER_PROTOCOL"] . ' ' . 400 . ' ' . 'Bad Request');
+ killme();
+ }
+
+ $arr = array('channel' => $r[0], 'request' => $_REQUEST, 'result' => $result);
+ call_hooks('webfinger',$arr);
+
+ json_return_and_die($arr['result'],'application/jrd+json');
+
+ }
+
+}
diff --git a/Zotlabs/Module/Xchan.php b/Zotlabs/Module/Xchan.php
new file mode 100644
index 000000000..526580fad
--- /dev/null
+++ b/Zotlabs/Module/Xchan.php
@@ -0,0 +1,47 @@
+<?php
+namespace Zotlabs\Module;
+
+
+
+class Xchan extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ $o = '<h3>' . t('Xchan Lookup') . '</h3>';
+
+ $o .= '<form action="xchan" method="get">';
+ $o .= t('Lookup xchan beginning with (or webbie): ');
+ $o .= '<input type="text" style="width:250px;" name="addr" value="' . $_GET['addr'] .'">';
+ $o .= '<input type="submit" name="submit" value="' . t('Submit') .'"></form>';
+ $o .= '<br><br>';
+
+ if(x($_GET, 'addr')) {
+ $addr = trim($_GET['addr']);
+
+ $r = q("select * from xchan where xchan_hash like '%s%%' or xchan_addr = '%s' group by xchan_hash",
+ dbesc($addr),
+ dbesc($addr)
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+ $o .= str_replace(array("\n", " "), array("<br>", "&nbsp;"), print_r($rr, true)) . EOL;
+
+ $s = q("select * from hubloc where hubloc_hash like '%s'",
+ dbesc($r[0]['xchan_hash'])
+ );
+
+ if($s) {
+ foreach($s as $rrr)
+ $o .= str_replace(array("\n", " "), array("<br>", "&nbsp;"), print_r($rrr, true)) . EOL;
+ }
+ }
+ }
+ else
+ notice( t('Not found.') . EOL);
+
+ }
+ return $o;
+ }
+
+}
diff --git a/Zotlabs/Module/Xpoco.php b/Zotlabs/Module/Xpoco.php
new file mode 100644
index 000000000..3ff05c4e1
--- /dev/null
+++ b/Zotlabs/Module/Xpoco.php
@@ -0,0 +1,13 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/socgraph.php');
+
+
+class Xpoco extends \Zotlabs\Web\Controller {
+
+ function init() {
+ poco($a,true);
+ }
+
+}
diff --git a/Zotlabs/Module/Xrd.php b/Zotlabs/Module/Xrd.php
new file mode 100644
index 000000000..d71fae695
--- /dev/null
+++ b/Zotlabs/Module/Xrd.php
@@ -0,0 +1,81 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/crypto.php');
+
+
+class Xrd extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $uri = urldecode(notags(trim($_GET['uri'])));
+ logger('xrd: ' . $uri,LOGGER_DEBUG);
+
+ $resource = $uri;
+
+ if(substr($uri,0,4) === 'http') {
+ $uri = str_replace('~','',$uri);
+ $name = basename($uri);
+ }
+ else {
+ $local = str_replace('acct:', '', $uri);
+ if(substr($local,0,2) == '//')
+ $local = substr($local,2);
+
+ $name = substr($local,0,strpos($local,'@'));
+ }
+
+ $r = q("SELECT * FROM channel WHERE channel_address = '%s' LIMIT 1",
+ dbesc($name)
+ );
+ if(! $r)
+ killme();
+
+ $dspr = replace_macros(get_markup_template('xrd_diaspora.tpl'),array(
+ '$baseurl' => z_root(),
+ '$dspr_guid' => $r[0]['channel_guid'] . str_replace('.','',\App::get_hostname()),
+ '$dspr_key' => base64_encode(pemtorsa($r[0]['channel_pubkey']))
+ ));
+
+ $salmon_key = salmon_key($r[0]['channel_pubkey']);
+
+ header('Access-Control-Allow-Origin: *');
+ header("Content-type: application/xrd+xml");
+
+
+ $aliases = array('acct:' . $r[0]['channel_address'] . '@' . \App::get_hostname(), z_root() . '/channel/' . $r[0]['channel_address'], z_root() . '/~' . $r[0]['channel_address']);
+
+ for($x = 0; $x < count($aliases); $x ++) {
+ if($aliases[$x] === $resource)
+ unset($aliases[$x]);
+ }
+
+
+ $o = replace_macros(get_markup_template('xrd_person.tpl'), array(
+ '$nick' => $r[0]['channel_address'],
+ '$accturi' => $resource,
+ '$aliases' => $aliases,
+ '$profile_url' => z_root() . '/channel/' . $r[0]['channel_address'],
+ '$hcard_url' => z_root() . '/hcard/' . $r[0]['channel_address'],
+ '$atom' => z_root() . '/feed/' . $r[0]['channel_address'],
+ '$zot_post' => z_root() . '/post/' . $r[0]['channel_address'],
+ '$poco_url' => z_root() . '/poco/' . $r[0]['channel_address'],
+ '$photo' => z_root() . '/photo/profile/l/' . $r[0]['channel_id'],
+ '$dspr' => $dspr,
+ // '$salmon' => z_root() . '/salmon/' . $r[0]['channel_address'],
+ // '$salmen' => z_root() . '/salmon/' . $r[0]['channel_address'] . '/mention',
+ '$modexp' => 'data:application/magic-public-key,' . $salmon_key,
+ '$subscribe' => z_root() . '/follow?url={uri}',
+ '$bigkey' => salmon_key($r[0]['channel_pubkey'])
+ ));
+
+
+ $arr = array('user' => $r[0], 'xml' => $o);
+ call_hooks('personal_xrd', $arr);
+
+ echo $arr['xml'];
+ killme();
+
+ }
+
+}
diff --git a/Zotlabs/Module/Xref.php b/Zotlabs/Module/Xref.php
new file mode 100644
index 000000000..e9d494da4
--- /dev/null
+++ b/Zotlabs/Module/Xref.php
@@ -0,0 +1,26 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Xref extends \Zotlabs\Web\Controller {
+
+ function init() {
+ // Sets a referral URL using an xchan directly
+ // Link format: example.com/xref/[xchan]/[TargetURL]
+ // Target URL is optional.
+ // Cookie lasts 24 hours to survive a browser restart. Contains no personal
+ // information at all - just somebody else's xchan.
+ $referrer = argv(1);
+ $expire=time()+60*60*2;
+ $path = 'xref';
+ setcookie($path, $referrer, $expire, "/");
+ $url = '';
+
+ if (argc() > 2)
+ $url = argv(2);
+
+ goaway (z_root() . '/' . $url);
+
+ }
+
+}
diff --git a/Zotlabs/Module/Zfinger.php b/Zotlabs/Module/Zfinger.php
new file mode 100644
index 000000000..2ff605fc9
--- /dev/null
+++ b/Zotlabs/Module/Zfinger.php
@@ -0,0 +1,18 @@
+<?php
+namespace Zotlabs\Module;
+
+
+class Zfinger extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ require_once('include/zot.php');
+ require_once('include/crypto.php');
+
+
+ $x = zotinfo($_REQUEST);
+ json_return_and_die($x);
+
+ }
+
+}
diff --git a/Zotlabs/Module/Zotfeed.php b/Zotlabs/Module/Zotfeed.php
new file mode 100644
index 000000000..28040149f
--- /dev/null
+++ b/Zotlabs/Module/Zotfeed.php
@@ -0,0 +1,52 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/items.php');
+require_once('include/zot.php');
+
+
+class Zotfeed extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $result = array('success' => false);
+
+ $mindate = (($_REQUEST['mindate']) ? datetime_convert('UTC','UTC',$_REQUEST['mindate']) : '');
+ if(! $mindate)
+ $mindate = datetime_convert('UTC','UTC', 'now - 14 days');
+
+ if(get_config('system','block_public') && (! get_account_id()) && (! remote_channel())) {
+ $result['message'] = 'Public access denied';
+ json_return_and_die($result);
+ }
+
+ $observer = \App::get_observer();
+
+
+ $channel_address = ((argc() > 1) ? argv(1) : '');
+ if($channel_address) {
+ $r = q("select channel_id, channel_name from channel where channel_address = '%s' and channel_removed = 0 limit 1",
+ dbesc(argv(1))
+ );
+ }
+ else {
+ $x = get_sys_channel();
+ if($x)
+ $r = array($x);
+ $mindate = datetime_convert('UTC','UTC', 'now - 14 days');
+ }
+ if(! $r) {
+ $result['message'] = 'Channel not found.';
+ json_return_and_die($result);
+ }
+
+ logger('zotfeed request: ' . $r[0]['channel_name'], LOGGER_DEBUG);
+
+ $result['messages'] = zot_feed($r[0]['channel_id'],$observer['xchan_hash'],array('mindate' => $mindate));
+ $result['success'] = true;
+ json_return_and_die($result);
+
+
+ }
+
+}
diff --git a/Zotlabs/Module/Zping.php b/Zotlabs/Module/Zping.php
new file mode 100644
index 000000000..d6128fa66
--- /dev/null
+++ b/Zotlabs/Module/Zping.php
@@ -0,0 +1,33 @@
+<?php
+namespace Zotlabs\Module; /** @file */
+
+require_once('include/zot.php');
+
+
+class Zping extends \Zotlabs\Web\Controller {
+
+ function get() {
+
+ // This is just a test utility function and may go away once we build these tools into
+ // the address book and directory to do dead site discovery.
+
+ // The response packet include the current URL and key so we can discover if the server
+ // has been re-installed and clean up (e.g. get rid of) any old hublocs and xchans.
+
+ // Remember to add '/post' to the url
+
+ if(! local_channel())
+ return;
+
+ $url = $_REQUEST['url'];
+
+ if(! $url)
+ return;
+
+
+ $m = zot_build_packet(\App::get_channel(),'ping');
+ $r = zot_zot($url,$m);
+ return print_r($r,true);
+
+ }
+}
diff --git a/Zotlabs/Web/CheckJS.php b/Zotlabs/Web/CheckJS.php
index 3ad5fc1ed..5f9856a8c 100644
--- a/Zotlabs/Web/CheckJS.php
+++ b/Zotlabs/Web/CheckJS.php
@@ -10,14 +10,25 @@ class CheckJS {
function __construct($test = 0) {
if(intval($_REQUEST['jsdisabled']))
$this->jsdisabled = 1;
+ else
+ $this->jsdisabled = 0;
if(intval($_COOKIE['jsdisabled']))
$this->jsdisabled = 1;
+ else
+ $this->jsdisabled = 0;
if(! $this->jsdisabled) {
$page = urlencode(\App::$query_string);
if($test) {
- \App::$page['htmlhead'] .= "\r\n" . '<meta http-equiv="refresh" content="0; url=' . z_root() . '/nojs?f=&redir=' . $page . '">' . "\r\n";
+
+ if(! array_key_exists('jsdisabled',$_COOKIE)) {
+ \App::$page['htmlhead'] .= "\r\n" . '<script>document.cookie="jsdisabled=0; path=/"; var jsMatch = /\&jsdisabled=0/; if (!jsMatch.exec(location.href)) { location.href = "' . z_root() . '/nojs/0?f=&redir=' . $page . '" ; }</script>' . "\r\n";
+ /* emulate JS cookie if cookies are not accepted */
+ if (array_key_exists('jsdisabled',$_GET)) {
+ $_COOKIE['jsdisabled'] = $_GET['jsdisabled'];
+ }
+ }
}
else {
\App::$page['htmlhead'] .= "\r\n" . '<noscript><meta http-equiv="refresh" content="0; url=' . z_root() . '/nojs?f=&redir=' . $page . '"></noscript>' . "\r\n";
diff --git a/Zotlabs/Web/Controller.php b/Zotlabs/Web/Controller.php
new file mode 100644
index 000000000..ac835e008
--- /dev/null
+++ b/Zotlabs/Web/Controller.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Zotlabs\Web;
+
+
+class Controller {
+
+ function init() {}
+ function post() {}
+ function get() {}
+
+} \ No newline at end of file
diff --git a/Zotlabs/Web/Router.php b/Zotlabs/Web/Router.php
index 29f2b5206..e6733ffdb 100644
--- a/Zotlabs/Web/Router.php
+++ b/Zotlabs/Web/Router.php
@@ -5,20 +5,32 @@ namespace Zotlabs\Web;
class Router {
+ private $modname = '';
+ private $controller = null;
+
function __construct(&$a) {
/**
*
* We have already parsed the server path into App::$argc and App::$argv
*
- * App::$argv[0] is our module name. We will load the file mod/{App::$argv[0]}.php
- * and use it for handling our URL request.
+ * App::$argv[0] is our module name. Let's call it 'foo'. We will load the
+ * Zotlabs/Module/Foo.php (object) or file mod/foo.php (procedural)
+ * and use it for handling our URL request to 'https://ourgreatwebsite.something/foo' .
* The module file contains a few functions that we call in various circumstances
* and in the following order:
*
- * "module"_init
- * "module"_post (only called if there are $_POST variables)
- * "module"_content - the string return of this function contains our page body
+ * Object:
+ * class Foo extends Zotlabs\Web\Controller {
+ * function init() { init function }
+ * function post() { post function }
+ * function get() { normal page function }
+ * }
+ *
+ * Procedual interface:
+ * foo_init()
+ * foo_post() (only called if there are $_POST variables)
+ * foo_content() - the string return of this function contains our page body
*
* Modules which emit other serialisations besides HTML (XML,JSON, etc.) should do
* so within the module init and/or post functions and then invoke killme() to terminate
@@ -26,6 +38,7 @@ class Router {
*/
$module = \App::$module;
+ $modname = "Zotlabs\\Module\\" . ucfirst($module);
if(strlen($module)) {
@@ -38,8 +51,13 @@ class Router {
if(is_array(\App::$plugins) && in_array($module,\App::$plugins) && file_exists("addon/{$module}/{$module}.php")) {
include_once("addon/{$module}/{$module}.php");
- if(function_exists($module . '_module'))
+ if(class_exists($modname)) {
+ $this->controller = new $modname;
\App::$module_loaded = true;
+ }
+ elseif(function_exists($module . '_module')) {
+ \App::$module_loaded = true;
+ }
}
if((strpos($module,'admin') === 0) && (! is_site_admin())) {
@@ -50,33 +68,54 @@ class Router {
/**
* If the site has a custom module to over-ride the standard module, use it.
- * Otherwise, look for the standard program module in the 'mod' directory
+ * Otherwise, look for the standard program module
*/
if(! (\App::$module_loaded)) {
- if(file_exists("mod/site/{$module}.php")) {
- include_once("mod/site/{$module}.php");
- \App::$module_loaded = true;
+ try {
+ $filename = 'Zotlabs/SiteModule/'. ucfirst($module). '.php';
+ if(file_exists($filename)) {
+ // This won't be picked up by the autoloader, so load it explicitly
+ require_once($filename);
+ $this->controller = new $modname;
+ \App::$module_loaded = true;
+ }
+ else {
+ $filename = 'Zotlabs/Module/'. ucfirst($module). '.php';
+ if(file_exists($filename)) {
+ $this->controller = new $modname;
+ \App::$module_loaded = true;
+ }
+ }
+ if(! \App::$module_loaded)
+ throw new \Exception('Module not found');
}
- elseif(file_exists("mod/{$module}.php")) {
- include_once("mod/{$module}.php");
- \App::$module_loaded = true;
+ catch(\Exception $e) {
+ if(file_exists("mod/site/{$module}.php")) {
+ include_once("mod/site/{$module}.php");
+ \App::$module_loaded = true;
+ }
+ elseif(file_exists("mod/{$module}.php")) {
+ include_once("mod/{$module}.php");
+ \App::$module_loaded = true;
+ }
}
- else logger("mod/{$module}.php not found.");
}
-
-
+
/**
- * This provides a place for plugins to register module handlers which don't otherwise exist on the system.
+ * This provides a place for plugins to register module handlers which don't otherwise exist
+ * on the system, or to completely over-ride an existing module.
* If the plugin sets 'installed' to true we won't throw a 404 error for the specified module even if
* there is no specific module file or matching plugin name.
* The plugin should catch at least one of the module hooks for this URL.
*/
- $x = array('module' => $module, 'installed' => false);
+ $x = array('module' => $module, 'installed' => \App::$module_loaded, 'controller' => $this->controller);
call_hooks('module_loaded', $x);
- if($x['installed'])
+ if($x['installed']) {
\App::$module_loaded = true;
+ $this->controller = $x['controller'];
+ }
/**
* The URL provided does not resolve to a valid module.
@@ -96,6 +135,8 @@ class Router {
killme();
}
+ logger("Module {$module} not found.", LOGGER_DEBUG, LOG_WARNING);
+
if((x($_SERVER, 'QUERY_STRING')) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && \App::$config['system']['dreamhost_error_hack']) {
logger('index.php: dreamhost_error_hack invoked. Original URI =' . $_SERVER['REQUEST_URI']);
goaway(z_root() . $_SERVER['REQUEST_URI']);
@@ -133,17 +174,20 @@ class Router {
* to over-ride them.
*/
- if(function_exists(\App::$module . '_init')) {
- $arr = array('init' => true, 'replace' => false);
- call_hooks(\App::$module . '_mod_init', $arr);
- if(! $arr['replace']) {
+ $arr = array('init' => true, 'replace' => false);
+ call_hooks(\App::$module . '_mod_init', $arr);
+ if(! $arr['replace']) {
+ if($this->controller && method_exists($this->controller,'init')) {
+ $this->controller->init();
+ }
+ elseif(function_exists(\App::$module . '_init')) {
$func = \App::$module . '_init';
$func($a);
}
}
/**
- * Do all theme initialiasion here before calling any additional module functions.
+ * Do all theme initialisation here before calling any additional module functions.
* The module_init function may have changed the theme.
* Additionally any page with a Comanche template may alter the theme.
* So we'll check for those now.
@@ -179,21 +223,30 @@ class Router {
}
}
- if(($_SERVER['REQUEST_METHOD'] === 'POST') && (! \App::$error)
- && (function_exists(\App::$module . '_post'))
- && (! x($_POST, 'auth-params'))) {
+ if(($_SERVER['REQUEST_METHOD'] === 'POST') && (! \App::$error) && (! x($_POST, 'auth-params'))) {
call_hooks(\App::$module . '_mod_post', $_POST);
- $func = \App::$module . '_post';
- $func($a);
+
+ if($this->controller && method_exists($this->controller,'post')) {
+ $this->controller->post();
+ }
+ elseif(function_exists(\App::$module . '_post')) {
+ $func = \App::$module . '_post';
+ $func($a);
+ }
}
- if((! \App::$error) && (function_exists(\App::$module . '_content'))) {
+ if(! \App::$error) {
$arr = array('content' => \App::$page['content'], 'replace' => false);
call_hooks(\App::$module . '_mod_content', $arr);
\App::$page['content'] = $arr['content'];
if(! $arr['replace']) {
- $func = \App::$module . '_content';
- $arr = array('content' => $func($a));
+ if($this->controller && method_exists($this->controller,'get')) {
+ $arr = array('content' => $this->controller->get());
+ }
+ elseif(function_exists(\App::$module . '_content')) {
+ $func = \App::$module . '_content';
+ $arr = array('content' => $func($a));
+ }
}
call_hooks(\App::$module . '_mod_aftercontent', $arr);
\App::$page['content'] .= $arr['content'];
diff --git a/boot.php b/boot.php
index ef620e3ec..78a6b7d32 100755
--- a/boot.php
+++ b/boot.php
@@ -47,10 +47,10 @@ require_once('include/account.php');
define ( 'PLATFORM_NAME', 'hubzilla' );
define ( 'RED_VERSION', trim(file_get_contents('version.inc')));
-define ( 'STD_VERSION', '1.4' );
+define ( 'STD_VERSION', '1.4.2' );
define ( 'ZOT_REVISION', 1 );
-define ( 'DB_UPDATE_VERSION', 1165 );
+define ( 'DB_UPDATE_VERSION', 1166 );
/**
@@ -860,6 +860,8 @@ class App {
if ((array_key_exists('0', self::$argv)) && strlen(self::$argv[0])) {
self::$module = str_replace(".", "_", self::$argv[0]);
self::$module = str_replace("-", "_", self::$module);
+ if(strpos(self::$module,'_') === 0)
+ self::$module = substr(self::$module,1);
} else {
self::$argc = 1;
self::$argv = array('home');
diff --git a/doc/context/channel/help.html b/doc/context/channel/help.html
deleted file mode 100644
index 810913ff3..000000000
--- a/doc/context/channel/help.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<script>
- var contextualHelp1 = function (target, openSidePanel) {
- $("#help-content").removeClass('help-content-open'); // Close the help panel
- $("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
- if (openSidePanel) {
- $("main").addClass('region_1-on'); // Open the side panel to highlight element
- } else {
- $("main").removeClass('region_1-on');
- }
- // Animate the page scroll to the element and then pulse the element to direct attention
- $('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
- for (i = 0; i < 3; i++) {
- $(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
- }
- }
-</script>
-<dl class="dl-horizontal">
- <dt>General</dt>
- <dd>This is the home page of a channel. It is similar to someone's profile "wall" in a social network context. Posts created by the channel are displayed according to the observer's viewing permissions.</dd>
- <dt>Create a Post</dt>
- <dd>If you have permission to create posts on the channel page, then you will see the post editor at the top.</dd>
- <dt><a href='#' onclick='contextualHelp1("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
- <dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
-</dl> \ No newline at end of file
diff --git a/doc/context/cloud/help.html b/doc/context/cloud/help.html
deleted file mode 100644
index 105947517..000000000
--- a/doc/context/cloud/help.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<script>
- var contextualHelp1 = function (target, openSidePanel) {
- $("#help-content").removeClass('help-content-open'); // Close the help panel
- $("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
- if (openSidePanel) {
- $("main").addClass('region_1-on'); // Open the side panel to highlight element
- } else {
- $("main").removeClass('region_1-on');
- }
- // Animate the page scroll to the element and then pulse the element to direct attention
- $('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
- for (i = 0; i < 3; i++) {
- $(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
- }
- }
-</script>
-<dl class="dl-horizontal">
- <dt>General</dt>
- <dd>This page displays a channel's "cloud" files. The files visible to the observer depend on the individual file permissions set by the channel owner. If you have permission to create/upload files you will see control buttons above the file list.</dd>
- <dt><a href='#' onclick='contextualHelp1("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
- <dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
-</dl> \ No newline at end of file
diff --git a/doc/context/admin/security/help.html b/doc/context/en/admin/security/help.html
index e9a741a5e..e9a741a5e 100644
--- a/doc/context/admin/security/help.html
+++ b/doc/context/en/admin/security/help.html
diff --git a/doc/context/en/channel/help.html b/doc/context/en/channel/help.html
new file mode 100644
index 000000000..6e3181cbf
--- /dev/null
+++ b/doc/context/en/channel/help.html
@@ -0,0 +1,8 @@
+<dl class="dl-horizontal">
+ <dt>General</dt>
+ <dd>This is the home page of a channel. It is similar to someone's profile "wall" in a social network context. Posts created by the channel are displayed according to the observer's viewing permissions.</dd>
+ <dt>Create a Post</dt>
+ <dd>If you have permission to create posts on the channel page, then you will see the post editor at the top.</dd>
+ <dt><a href='#' onclick='contextualHelpFocus("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
+ <dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
+</dl> \ No newline at end of file
diff --git a/doc/context/en/cloud/help.html b/doc/context/en/cloud/help.html
new file mode 100644
index 000000000..a8f193223
--- /dev/null
+++ b/doc/context/en/cloud/help.html
@@ -0,0 +1,6 @@
+<dl class="dl-horizontal">
+ <dt>General</dt>
+ <dd>This page displays a channel's "cloud" files. The files visible to the observer depend on the individual file permissions set by the channel owner. If you have permission to create/upload files you will see control buttons above the file list.</dd>
+ <dt><a href='#' onclick='contextualHelpFocus("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
+ <dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
+</dl> \ No newline at end of file
diff --git a/doc/context/mail/help.html b/doc/context/en/mail/help.html
index a2361a135..a2361a135 100644
--- a/doc/context/mail/help.html
+++ b/doc/context/en/mail/help.html
diff --git a/doc/context/network/help.html b/doc/context/en/network/help.html
index 956af7380..53e993b69 100644
--- a/doc/context/network/help.html
+++ b/doc/context/en/network/help.html
@@ -1,25 +1,9 @@
-<script>
- var contextualHelp1 = function (target, openSidePanel) {
- $("#help-content").removeClass('help-content-open'); // Close the help panel
- $("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
- if (openSidePanel) {
- $("main").addClass('region_1-on'); // Open the side panel to highlight element
- } else {
- $("main").removeClass('region_1-on');
- }
- // Animate the page scroll to the element and then pulse the element to direct attention
- $('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
- for (i = 0; i < 3; i++) {
- $(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
- }
- }
-</script>
<dl class="dl-horizontal">
<dt>General</dt>
<dd>The network page displays a stream of posts and conversations, typically ordered by the most recently updated. This page is highly customizable.</dd>
- <dt><a href='#' onclick='contextualHelp1("#profile-jot-wrapper", 0); return false;' title="Click to highlight element...">Create a Post</a></dt>
+ <dt><a href='#' onclick='contextualHelpFocus("#profile-jot-wrapper", 0); return false;' title="Click to highlight element...">Create a Post</a></dt>
<dd>At the top of the page there is a text box that says "Share". Clicking this box opens a new post editor. The post editor is customizable, but the basic editor provides fields for a post body and an optional post <b>Title</b>. Buttons below the text area to the left provide shortcuts to text formatting and inserting links, images, and other data into the post. The buttons to the right provide a post preview, the post permissions setting, and a <b>Submit</b> button to send the post.</dd>
- <dt><a href='#' onclick='contextualHelp1("#group-sidebar", 1); return false;' title="Click to highlight element...">Privacy Groups</a></dt>
+ <dt><a href='#' onclick='contextualHelpFocus("#group-sidebar", 1); return false;' title="Click to highlight element...">Privacy Groups</a></dt>
<dd>The privacy groups you have created are displayed in the side panel. Selecting them filters posts to those created by channels in the chosen group.</dd>
<dt><a href='#' onclick='$("#dbtn-acl").click(); return false;' title="Click to highlight element...">Post Permissions</a></dt>
<dd>The access control list (ACL) is what you use to set who can see your new post. Pressing the ACL button beside the Submit button will display a dialog in which you can select what channels and/or privacy groups can see the post. You can also select who is explicitly denied access. For example, say you are planning a surprise party for a friend. You can send an invitation post to everyone in your <b>Friends</b> group <i>except</i> the friend you are surprising. In this case you "show" the <b>Friends</b> group but "don't show" that one person.</dd>
diff --git a/doc/context/en/photos/help.html b/doc/context/en/photos/help.html
new file mode 100644
index 000000000..78b442bb4
--- /dev/null
+++ b/doc/context/en/photos/help.html
@@ -0,0 +1,6 @@
+<dl class="dl-horizontal">
+ <dt>General</dt>
+ <dd>This page displays a channel's photo albums. The images visible to the observer depend on the individual image permissions.</dd>
+ <dt><a href='#' onclick='contextualHelpFocus("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
+ <dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
+</dl> \ No newline at end of file
diff --git a/doc/context/en/profile/help.html b/doc/context/en/profile/help.html
new file mode 100644
index 000000000..563e0df99
--- /dev/null
+++ b/doc/context/en/profile/help.html
@@ -0,0 +1,6 @@
+<dl class="dl-horizontal">
+ <dt>General</dt>
+ <dd>This is the profile page of a channel. It typically displays information describing the channel. If the channel represents a person in a social network, for example, then the profile might provide contact information and other personal details about the person. Channels can have multiple profiles, where the displayed profile depends on the observer.</dd>
+ <dt><a href='#' onclick='contextualHelpFocus("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
+ <dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
+</dl> \ No newline at end of file
diff --git a/doc/context/photos/help.html b/doc/context/photos/help.html
deleted file mode 100644
index f41611f8d..000000000
--- a/doc/context/photos/help.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<script>
- var contextualHelp1 = function (target, openSidePanel) {
- $("#help-content").removeClass('help-content-open'); // Close the help panel
- $("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
- if (openSidePanel) {
- $("main").addClass('region_1-on'); // Open the side panel to highlight element
- } else {
- $("main").removeClass('region_1-on');
- }
- // Animate the page scroll to the element and then pulse the element to direct attention
- $('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
- for (i = 0; i < 3; i++) {
- $(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
- }
- }
-</script>
-<dl class="dl-horizontal">
- <dt>General</dt>
- <dd>This page displays a channel's photo albums. The images visible to the observer depend on the individual image permissions.</dd>
- <dt><a href='#' onclick='contextualHelp1("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
- <dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
-</dl> \ No newline at end of file
diff --git a/doc/context/profile/help.html b/doc/context/profile/help.html
deleted file mode 100644
index 0d4abb8cb..000000000
--- a/doc/context/profile/help.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<script>
- var contextualHelp1 = function (target, openSidePanel) {
- $("#help-content").removeClass('help-content-open'); // Close the help panel
- $("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
- if (openSidePanel) {
- $("main").addClass('region_1-on'); // Open the side panel to highlight element
- } else {
- $("main").removeClass('region_1-on');
- }
- // Animate the page scroll to the element and then pulse the element to direct attention
- $('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
- for (i = 0; i < 3; i++) {
- $(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
- }
- }
-</script>
-<dl class="dl-horizontal">
- <dt>General</dt>
- <dd>This is the profile page of a channel. It typically displays information describing the channel. If the channel represents a person in a social network, for example, then the profile might provide contact information and other personal details about the person. Channels can have multiple profiles, where the displayed profile depends on the observer.</dd>
- <dt><a href='#' onclick='contextualHelp1("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
- <dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
-</dl> \ No newline at end of file
diff --git a/doc/plugins.bb b/doc/plugins.bb
index f74276038..f96fb8dee 100644
--- a/doc/plugins.bb
+++ b/doc/plugins.bb
@@ -1,6 +1,6 @@
[b]Plugins[/b]
-So you want to make the $Projectname do something it doesn't already do. There are lots of ways. But let's learn how to write a plugin or addon.
+So you want to make $Projectname do something it doesn't already do. There are lots of ways. But let's learn how to write a plugin or addon.
In your $Projectname folder/directory, you will probably see a sub-directory called 'addon'. If you don't have one already, go ahead and create it.
@@ -45,16 +45,16 @@ In our case, we'll call them randplace_load() and randplace_unload(), as that is
pluginname_uninstall()
[/code]
-Next we'll talk about **hooks**. Hooks are places in the $Projectname code where we allow plugins to do stuff. There are a [lot of these](help/Hooks), and they each have a name. What we normally do is use the pluginname_load() function to register a &quot;handler function&quot; for any hooks you are interested in. Then when any of these hooks are triggered, your code will be called.
+Next we'll talk about [b]hooks[/b]. Hooks are places in the $Projectname code where we allow plugins to do stuff. There are a [url=[baseurl]/help/hooklist]lot of these[/url], and they each have a name. What we normally do is use the pluginname_load() function to register a &quot;handler function&quot; for any hooks you are interested in. Then when any of these hooks are triggered, your code will be called.
-We register hook handlers with the 'register_hook()' function. It takes 3 arguments. The first is the hook we wish to catch, the second is the filename of the file to find our handler function (relative to the base of your $Projectname installation), and the third is the function name of your handler function. So let's create our randplace_load() function right now.
+We register hook handlers with the 'Zotlabs\Extend\Hook::register()' function. It typically takes 3 arguments. The first is the hook we wish to catch, the second is the filename of the file to find our handler function (relative to the base of your $Projectname installation), and the third is the function name of your handler function. So let's create our randplace_load() function right now.
[code]
function randplace_load() {
- register_hook('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
+ Zotlabs\Extend\Hook::register('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
- register_hook('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
- register_hook('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
+ Zotlabs\Extend\Hook::register('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
+ Zotlabs\Extend\Hook::register('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
}
[/code]
@@ -64,21 +64,18 @@ So we're going to catch three events, 'post_local' which is triggered when a pos
Next we'll create an unload function. This is easy, as it just unregisters our hooks. It takes exactly the same arguments.
[code]
function randplace_unload() {
- unregister_hook('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
-
- unregister_hook('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
- unregister_hook('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
+ Zotlabs\Extend\Hook::unregister('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
+ Zotlabs\Extend\Hook::unregister('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
+ Zotlabs\Extend\Hook::unregister('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
}
[/code]
-Hooks are called with two arguments. The first is always $a, which is our global App structure and contains a huge amount of information about the state of the web request we are processing; as well as who the viewer is, and what our login state is, and the current contents of the web page we're probably constructing.
-
-The second argument is specific to the hook you're calling. It contains information relevant to that particular place in the program, and often allows you to look at, and even change it. In order to change it, you need to add '&amp;' to the variable name so it is passed to your function by reference. Otherwise it will create a copy and any changes you make will be lost when the hook process returns. Usually (but not always) the second argument is a named array of data structures. Please see the &quot;hook reference&quot; (not yet written as of this date) for details on any specific hook. Occasionally you may need to view the program source to see precisely how a given hook is called and how the results are processed.
+Hooks are always called with one argument which is specific to the hook you're calling. It contains information relevant to that particular place in the program, and often allows you to look at, and even change it. In order to change it, you need to add '&amp;' to the variable name so it is passed to your function by reference. Otherwise it will create a copy and any changes you make will be lost when the hook process returns. Usually (but not always) the passed data is a named array of data structures. Please see the &quot;hook reference&quot; (not yet written as of this date) for details on any specific hook. Occasionally you may need to view the program source to see precisely how a given hook is called and how the results are processed.
Let's go ahead and add some code to implement our post_local hook handler.
[code]
- function randplace_post_hook($a, &amp;$item) {
+ function randplace_post_hook(&amp;$item) {
/**
*
@@ -145,7 +142,7 @@ Now let's add our functions to create and store preference settings.
*
*/
- function randplace_settings_post($a,$post) {
+ function randplace_settings_post($post) {
if(! local_channel())
return;
if($_POST['randplace-submit'])
@@ -171,7 +168,7 @@ Now let's add our functions to create and store preference settings.
- function randplace_settings(&amp;$a,&amp;$s) {
+ function randplace_settings(&amp;$s) {
if(! local_channel())
return;
@@ -205,19 +202,46 @@ Now let's add our functions to create and store preference settings.
-***Advanced Plugins***
+[h2]Advanced Plugins[/h2]
Sometimes your plugins want to provide a range of new functionality which isn't provided at all or is clumsy to provide using hooks. In this case your plugin can also act as a 'module'. A module in our case refers to a structured webpage handler which responds to a given URL. Then anything which accesses that URL will be handled completely by your plugin.
-The key to this is to create a simple function named pluginname_module() which does nothing.
+There are two ways to accomplish this. To create a module object use the following model:
+[code]
+<?php /* file: addon/randplace/Mod_Randplace.php */
+namespace Zotlabs\Module;
+
+ // Your module will consist of the name of your addon with an uppercase first character, within the Zotlabs\Module namespace
+ // To avoid namespace conflicts with your plugin, the convention we're using is to name the module file Mod_Addonname.php
+ // In this case 'Mod_Randplace.php' and then include it from within your main plugin file 'randplace.php' with the line:
+ //
+ // require_once('addon/randplace/Mod_Randplace.php');
+
+ class Randplace extends \Zotlabs\Web\Controller {
+ function init() {
+ // init method is always called first if it exists
+ }
+ function post() {
+ // the post method is only called if there are $_POST variables present (e.g. the page request method is "post")
+ }
+ function get() {
+ // The get method is used to display normal content on the page
+ // whatever this function returns will be displayed in the page body
+ }
+ }
+[/code]
+
+The other option is to use a procedural interface. The $a argument to these function is obsolete, but must be present.
+The key to this is to create a simple function named pluginname_module() which does nothing. These lines and this interface
+can be used inside your addon file without causing a namespace conflict, as the object method will.
+
[code]
function randplace_module() { return; }
[/code]
-Once this function exists, the URL #^[url=https://yoursite/randplace]https://yoursite/randplace[/url] will access your plugin as a module. Then you can define functions which are called at various points to build a webpage just like the modules in the mod/ directory. The typical functions and the order which they are called is
+Once this function exists, the URL #^[url=https://yoursite/randplace]https://yoursite/randplace[/url] will access your plugin as a module. Then you can define functions which are called at various points to return or process a structured webpage just like system modules. The typical functions and the order which they are called is
[code]
modulename_init($a) // (e.g. randplace_init($a);) called first - if you wish to emit json or xml,
// you should do it here, followed by killme() which will avoid the default action of building a webpage
- modulename_aside($a) // Often used to create sidebar content
modulename_post($a) // Called whenever the page is accessed via the &quot;post&quot; method
modulename_content($a) // called to generate the central page content. This function should return a string
// consisting of the central page content.
@@ -228,7 +252,7 @@ Your module functions have access to the URL path as if they were standalone pro
[/code]
we will create an argc/argv list for use by your module functions
[code]
- $x = argc(); $x will be 4, the number of path arguments after the sitename
+ $x = argc(); // $x will be 4, the number of path arguments after the sitename
for($x = 0; $x &lt; argc(); $x ++)
echo $x . ' ' . argv($x);
@@ -259,6 +283,6 @@ The $Projectname has _install and _uninstall functions but these are used differ
[li] Friendica's &quot;plugin_settings_post&quot; hook is called &quot;feature_settings_post&quot;[/li]
-Changing these will often allow your plugin to function, but please double check all your permission and identity code because the concepts behind it are completely different in the $Projectname. Many structured data names (especially DB schema columns) are also quite different.
+Changing these will often allow your plugin to function, but please double check all your permission and identity code because the concepts behind it are completely different in $Projectname. Many structured data names (especially DB schema columns) are also quite different.
#include doc/macros/main_footer.bb;
diff --git a/include/api.php b/include/api.php
index fd644947c..e64c86695 100644
--- a/include/api.php
+++ b/include/api.php
@@ -772,13 +772,15 @@ require_once('include/api_auth.php');
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
$_FILES['userfile'] = $_FILES['media'];
- require_once('mod/wall_attach.php');
- $posted = wall_attach_post($a);
-
- //now that we have the img url in bbcode we can add it to the status and insert the wall item.
+
+ $mod = new Zotlabs\Module\Wall_attach();
+ $mod->post();
+
+
$_REQUEST['body']=$txt."\n\n".$posted;
- require_once('mod/item.php');
- item_post($a);
+
+ $mod = new Zotlabs\Module\Item();
+ $mod->post();
// this should output the last post (the one we just posted).
return api_status_show($a,$type);
@@ -871,9 +873,9 @@ require_once('include/api_auth.php');
// upload each image if we have any
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- require_once('mod/wall_attach.php');
+ $mod = new Zotlabs\Module\Wall_attach();
App::$data['api_info'] = $user_info;
- $media = wall_attach_post($a);
+ $media = $mod->post();
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n" . $media;
@@ -884,9 +886,9 @@ require_once('include/api_auth.php');
$_FILES['userfile'] = $_FILES['media'];
// upload each image if we have any
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- require_once('mod/wall_attach.php');
+ $mod = new Zotlabs\Module\Wall_attach();
App::$data['api_info'] = $user_info;
- $media = wall_attach_post($a);
+ $media = $mod->post();
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n" . $media;
@@ -896,8 +898,8 @@ require_once('include/api_auth.php');
// call out normal post function
- require_once('mod/item.php');
- item_post($a);
+ $mod = new Zotlabs\Module\Item();
+ $mod->post();
// this should output the last post (the one we just posted).
return api_status_show($a,$type);
@@ -926,14 +928,14 @@ require_once('include/api_auth.php');
$_FILES['userfile'] = $_FILES['media'];
// upload the image if we have one
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- require_once('mod/wall_upload.php');
- $media = wall_upload_post($a);
+ $mod = new Zotlabs\Module\Wall_upload();
+ $media = $mod->post();
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n".$media;
}
- require_once('mod/item.php');
- $x = item_post($a);
+ $mod = new Zotlabs\Module\Item();
+ $x = $mod->post();
json_return_and_die($x);
}
@@ -1423,9 +1425,8 @@ require_once('include/api_auth.php');
$_REQUEST['profile_uid'] = api_user();
$_REQUEST['type'] = 'wall';
$_REQUEST['api_source'] = true;
-
- require_once('mod/item.php');
- item_post($a);
+ $mod = new Zotlabs\Module\Item();
+ $mod->post();
}
}
else
diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php
index 1ed57bfd4..9167cb5ad 100644
--- a/include/bb2diaspora.php
+++ b/include/bb2diaspora.php
@@ -270,7 +270,14 @@ function bb2dmention_callback($match) {
function bb2diaspora_itemwallwall(&$item) {
+ // We will provide wallwall (embedded author on the Diaspora side) if
+ // 1. It is a wall-to-wall post
+ // 2. A comment arrived which has no Diaspora signature info
+
+
+ $wallwall = false;
$author_exists = true;
+
if(! array_key_exists('author',$item)) {
$author_exists = false;
logger('bb2diaspora_itemwallwall: no author');
@@ -281,11 +288,21 @@ function bb2diaspora_itemwallwall(&$item) {
$item['author'] = $r[0];
}
- if(($item['mid'] == $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && (is_array($item['author']))) {
- logger('bb2diaspora_itemwallwall: author: ' . print_r($item['author'],true), LOGGER_DATA);
+ $has_meta = false;
+ if($item['diaspora_meta'] || get_iconfig($item,'diaspora','fields'))
+ $has_meta = true;
+
+ if($item['author_xchan'] != $item['owner_xchan']) {
+ if($item['mid'] == $item['parent_mid'])
+ $wallwall = true;
+ else {
+ if(! $has_meta) {
+ $wallwall = true;
+ }
+ }
}
- if(($item['mid'] == $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && (is_array($item['author'])) && $item['author']['xchan_url'] && $item['author']['xchan_name'] && $item['author']['xchan_photo_m']) {
+ if(($wallwall) && (is_array($item['author'])) && $item['author']['xchan_url'] && $item['author']['xchan_name'] && $item['author']['xchan_photo_m']) {
logger('bb2diaspora_itemwallwall: wall to wall post',LOGGER_DEBUG);
// post will come across with the owner's identity. Throw a preamble onto the post to indicate the true author.
$item['body'] = "\n\n"
@@ -301,7 +318,12 @@ function bb2diaspora_itemwallwall(&$item) {
}
-function bb2diaspora_itembody($item, $force_update = false) {
+function bb2diaspora_itembody($item, $force_update = false, $have_channel = false) {
+
+
+ if(! get_iconfig($item,'diaspora','fields')) {
+ $force_update = true;
+ }
$matches = array();
@@ -339,8 +361,8 @@ function bb2diaspora_itembody($item, $force_update = false) {
}
}
-
- bb2diaspora_itemwallwall($newitem);
+ if(! $have_channel)
+ bb2diaspora_itemwallwall($newitem);
$title = $newitem['title'];
$body = preg_replace('/\#\^http/i', 'http', $newitem['body']);
diff --git a/include/help.php b/include/help.php
new file mode 100644
index 000000000..13473164d
--- /dev/null
+++ b/include/help.php
@@ -0,0 +1,150 @@
+<?php
+
+function load_doc_file($s) {
+ $lang = \App::$language;
+ if(! isset($lang))
+ $lang = 'en';
+ $b = basename($s);
+ $d = dirname($s);
+
+ $c = find_doc_file("$d/$lang/$b");
+ if($c)
+ return $c;
+ $c = find_doc_file($s);
+ if($c)
+ return $c;
+ return '';
+}
+
+function find_doc_file($s) {
+ if(file_exists($s))
+ return file_get_contents($s);
+ return '';
+}
+
+function search_doc_files($s) {
+
+ $a = get_app();
+
+ $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']));
+
+ $regexop = db_getfunc('REGEXP');
+
+ $r = q("select item_id.sid, item.* from item left join item_id on item.id = item_id.iid where service = 'docfile' and
+ body $regexop '%s' and item_type = %d $pager_sql",
+ dbesc($s),
+ intval(ITEM_TYPE_DOC)
+ );
+
+ $r = fetch_post_tags($r,true);
+
+ for($x = 0; $x < count($r); $x ++) {
+
+ $r[$x]['text'] = $r[$x]['body'];
+
+ $r[$x]['rank'] = 0;
+ if($r[$x]['term']) {
+ foreach($r[$x]['term'] as $t) {
+ if(stristr($t['term'],$s)) {
+ $r[$x]['rank'] ++;
+ }
+ }
+ }
+ if(stristr($r[$x]['sid'],$s))
+ $r[$x]['rank'] ++;
+ $r[$x]['rank'] += substr_count(strtolower($r[$x]['text']),strtolower($s));
+ // bias the results to the observer's native language
+ if($r[$x]['lang'] === \App::$language)
+ $r[$x]['rank'] = $r[$x]['rank'] + 10;
+
+ }
+ usort($r,'doc_rank_sort');
+ return $r;
+}
+
+
+function doc_rank_sort($s1,$s2) {
+ if($s1['rank'] == $s2['rank'])
+ return 0;
+ return (($s1['rank'] < $s2['rank']) ? 1 : (-1));
+}
+
+
+function load_context_help() {
+
+ $path = App::$cmd;
+ $args = App::$argv;
+ $lang = App::$language;
+
+ if(! isset($lang) || !is_dir('doc/context/' . $lang . '/')) {
+ $lang = 'en';
+ }
+ while($path) {
+ $context_help = load_doc_file('doc/context/' . $lang . '/' . $path . '/help.html');
+ if(!$context_help) {
+ // Fallback to English if the translation is absent
+ $context_help = load_doc_file('doc/context/en/' . $path . '/help.html');
+ }
+ if($context_help)
+ break;
+ array_pop($args);
+ $path = implode($args,'/');
+ }
+
+ return $context_help;
+}
+
+
+function store_doc_file($s) {
+
+ if(is_dir($s))
+ return;
+
+ $item = array();
+ $sys = get_sys_channel();
+
+ $item['aid'] = 0;
+ $item['uid'] = $sys['channel_id'];
+
+
+ if(strpos($s,'.md'))
+ $mimetype = 'text/markdown';
+ elseif(strpos($s,'.html'))
+ $mimetype = 'text/html';
+ else
+ $mimetype = 'text/bbcode';
+
+ require_once('include/html2plain.php');
+
+ $item['body'] = html2plain(prepare_text(file_get_contents($s),$mimetype, true));
+ $item['mimetype'] = 'text/plain';
+
+ $item['plink'] = z_root() . '/' . str_replace('doc','help',$s);
+ $item['owner_xchan'] = $item['author_xchan'] = $sys['channel_hash'];
+ $item['item_type'] = ITEM_TYPE_DOC;
+
+ $r = q("select item.* from item left join item_id on item.id = item_id.iid where service = 'docfile' and
+ sid = '%s' and item_type = %d limit 1",
+ dbesc($s),
+ intval(ITEM_TYPE_DOC)
+ );
+
+ if($r) {
+ $item['id'] = $r[0]['id'];
+ $item['mid'] = $item['parent_mid'] = $r[0]['mid'];
+ $x = item_store_update($item);
+ }
+ else {
+ $item['mid'] = $item['parent_mid'] = item_message_id();
+ $x = item_store($item);
+ }
+
+ if($x['success']) {
+ update_remote_id($sys,$x['item_id'],ITEM_TYPE_DOC,$s,'docfile',0,$item['mid']);
+ }
+
+
+}
+
diff --git a/include/importdoc.php b/include/importdoc.php
index 10f868697..90dfb2fc4 100755
--- a/include/importdoc.php
+++ b/include/importdoc.php
@@ -9,7 +9,7 @@ function importdoc_run($argv, $argc){
cli_startup();
- require_once('mod/help.php');
+ require_once('include/help.php');
update_docs_dir('doc/*');
diff --git a/include/items.php b/include/items.php
index 95822c0ba..014e626b6 100755
--- a/include/items.php
+++ b/include/items.php
@@ -555,8 +555,8 @@ function get_public_feed($channel, $params) {
// put a sane lower limit on feed requests if not specified
- if($params['begin'] === NULL_DATE)
- $params['begin'] = datetime_convert('UTC','UTC','now - 1 month');
+// if($params['begin'] === NULL_DATE)
+// $params['begin'] = datetime_convert('UTC','UTC','now - 1 month');
switch($params['type']) {
case 'json':
@@ -4235,10 +4235,10 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
$obj = ((is_array($item['obj'])) ? $item['object'] : json_decode($item['object'],true));
$o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
- $o .= '<summary>' . xmlify(bbcode($obj['title'])) . '</summary>' . "\r\n";
+ $o .= '<summary xmlns="urn:ietf:params:xml:ns:xcal">' . xmlify(bbcode($obj['title'])) . '</summary>' . "\r\n";
$o .= '<dtstart xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['start'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtstart>' . "\r\n";
$o .= '<dtend xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['finish'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtend>' . "\r\n";
- $o .= '<location>' . bbcode($obj['location']) . '</location>' . "\r\n";
+ $o .= '<location xmlns="urn:ietf:params:xml:ns:xcal">' . xmlify(bbcode($obj['location'])) . '</location>' . "\r\n";
$o .= '<content type="' . $type . '" >' . xmlify(bbcode($obj['description'])) . '</content>' . "\r\n";
}
else {
diff --git a/include/nav.php b/include/nav.php
index 541ab3aed..c59aaae37 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -150,9 +150,15 @@ EOT;
$help_url = z_root() . '/help?f=&cmd=' . App::$cmd;
if(! get_config('system','hide_help')) {
- require_once('mod/help.php');
- $context_help = load_context_help();
- $nav['help'] = array($help_url, t('Help'), "", t('Help and documentation'),'help_nav_btn',$context_help);
+ $context_help = '';
+ $enable_context_help = ((intval(get_config('system','enable_context_help')) === 1 || get_config('system','enable_context_help') === false) ? true : false);
+ if($enable_context_help === true) {
+ require_once('include/help.php');
+ $context_help = load_context_help();
+ //direct directly to /help if $context_help is empty - this can be removed once we have context help for all modules
+ $enable_context_help = (($context_help) ? true : false);
+ }
+ $nav['help'] = array($help_url, t('Help'), "", t('Help and documentation'), 'help_nav_btn', $context_help, $enable_context_help);
}
if(! UNO)
@@ -234,6 +240,12 @@ $powered_by = '';
// $powered_by = '<strong>red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="r#" />matrix</strong>';
+ $tpl = get_markup_template('nav_header.tpl');
+
+ App::$page['htmlhead'] .= replace_macros($tpl, array(
+ '$enable_context_help' => $enable_context_help
+ ));
+
$tpl = get_markup_template('nav.tpl');
App::$page['nav'] .= replace_macros($tpl, array(
@@ -248,7 +260,7 @@ $powered_by = '';
'$powered_by' => $powered_by,
'$help' => t('@name, #tag, ?doc, content'),
'$pleasewait' => t('Please wait...')
- ));
+ ));
call_hooks('page_header', App::$page['nav']);
}
diff --git a/include/notifier.php b/include/notifier.php
index 628847d54..4435c7497 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -450,7 +450,6 @@ function notifier_run($argv, $argc){
'target_item' => $target_item,
'top_level_post' => $top_level_post,
'private' => $private,
- 'followup' => $followup,
'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink,
'cmd' => $cmd,
@@ -547,7 +546,6 @@ function notifier_run($argv, $argc){
'hub' => $hub,
'top_level_post' => $top_level_post,
'private' => $private,
- 'followup' => $followup,
'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink,
'cmd' => $cmd,
diff --git a/include/photos.php b/include/photos.php
index 943d7d503..24e872890 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -706,3 +706,43 @@ function gps2Num($coordPart) {
return floatval($parts[0]) / floatval($parts[1]);
}
+
+function profile_photo_set_profile_perms($profileid = '') {
+
+ $allowcid = '';
+ if (x($profileid)) {
+
+ $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.id = %d OR profile.profile_guid = '%s' LIMIT 1", intval($profileid), dbesc($profileid));
+
+ } else {
+
+ logger('Resetting permissions on default-profile-photo for user'.local_channel());
+ $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.uid = %d AND is_default = 1 LIMIT 1", intval(local_channel()) ); //If no profile is given, we update the default profile
+ }
+
+ $profile = $r[0];
+ if(x($profile['id']) && x($profile['photo'])) {
+ preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
+ $resource_id = $resource_id[0];
+
+ if (intval($profile['is_default']) != 1) {
+ $r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1", intval(local_channel()) );
+ $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ", intval($profile['id'])); //Should not be needed in future. Catches old int-profile-ids.
+ $r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'", dbesc($profile['profile_guid']));
+ $allowcid = "<" . $r0[0]['channel_hash'] . ">";
+ foreach ($r1 as $entry) {
+ $allowcid .= "<" . $entry['abook_xchan'] . ">";
+ }
+ foreach ($r2 as $entry) {
+ $allowcid .= "<" . $entry['abook_xchan'] . ">";
+ }
+
+ q("UPDATE `photo` SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",dbesc($allowcid),dbesc($resource_id),intval($profile['uid']));
+
+ } else {
+ q("UPDATE `photo` SET allow_cid = '' WHERE profile = 1 AND uid = %d",intval($profile['uid'])); //Reset permissions on default profile picture to public
+ }
+ }
+
+ return;
+ }
diff --git a/include/plugin.php b/include/plugin.php
index 8dceb8fb1..80e3ae20e 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -185,7 +185,7 @@ function register_hook($hook, $file, $function, $priority = 0) {
dbesc($file),
dbesc($function)
);
- if(count($r))
+ if($r)
return true;
$r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`) VALUES ( '%s', '%s', '%s', '%s' )",
@@ -226,9 +226,8 @@ function unregister_hook($hook, $file, $function) {
function load_hooks() {
- $a = get_app();
-// if(! is_array(App::$hooks))
- App::$hooks = array();
+
+ App::$hooks = array();
$r = q("SELECT * FROM hook WHERE true ORDER BY priority DESC");
if($r) {
@@ -236,10 +235,10 @@ function load_hooks() {
if(! array_key_exists($rr['hook'],App::$hooks))
App::$hooks[$rr['hook']] = array();
- App::$hooks[$rr['hook']][] = array($rr['file'],$rr['function']);
+ App::$hooks[$rr['hook']][] = array($rr['file'],$rr['function'],$rr['priority'],$rr['hook_version']);
}
}
-//logger('hooks: ' . print_r(App::$hooks,true));
+ //logger('hooks: ' . print_r(App::$hooks,true));
}
/**
@@ -259,15 +258,15 @@ function load_hooks() {
* @param string $fn
* function name of callback handler
*/
-function insert_hook($hook, $fn) {
- $a = get_app();
+function insert_hook($hook, $fn, $version = 0, $priority = 0) {
+
if(! is_array(App::$hooks))
App::$hooks = array();
if(! array_key_exists($hook, App::$hooks))
App::$hooks[$hook] = array();
- App::$hooks[$hook][] = array('', $fn);
+ App::$hooks[$hook][] = array('', $fn, $priority, $version);
}
/**
@@ -280,8 +279,7 @@ function insert_hook($hook, $fn) {
* @param string|array &$data to transmit to the callback handler
*/
function call_hooks($name, &$data = null) {
- $a = get_app();
-
+ $a = 0;
if((is_array(App::$hooks)) && (array_key_exists($name, App::$hooks))) {
foreach(App::$hooks[$name] as $hook) {
if($hook[0])
@@ -289,9 +287,11 @@ function call_hooks($name, &$data = null) {
if(function_exists($hook[1])) {
$func = $hook[1];
- $func($a, $data);
+ if($hook[3])
+ $func($data);
+ else
+ $func($a, $data);
} else {
-
q("DELETE FROM hook WHERE hook = '%s' AND file = '%s' AND function = '%s'",
dbesc($name),
dbesc($hook[0]),
@@ -535,8 +535,11 @@ function format_css_if_exists($source) {
else
$path = theme_include($source[0]);
- if($path)
- return '<link rel="stylesheet" href="' . script_path() . '/' . $path . '" type="text/css" media="' . $source[1] . '">' . "\r\n";
+ if($path) {
+ $path = script_path() . '/' . $path;
+ $qstring = ((parse_url($path, PHP_URL_QUERY)) ? '&' : '?') . 'v=' . STD_VERSION;
+ return '<link rel="stylesheet" href="' . $path . $qstring . '" type="text/css" media="' . $source[1] . '">' . "\r\n";
+ }
}
/*
@@ -612,8 +615,11 @@ function format_js_if_exists($source) {
$path = $source;
else
$path = theme_include($source);
- if($path)
- return '<script src="' . script_path() . '/' . $path . '" ></script>' . "\r\n" ;
+ if($path) {
+ $path = script_path() . '/' . $path;
+ $qstring = ((parse_url($path, PHP_URL_QUERY)) ? '&' : '?') . 'v=' . STD_VERSION;
+ return '<script src="' . $path . $qstring . '" ></script>' . "\r\n" ;
+ }
}
@@ -678,4 +684,4 @@ function folder_exists($folder)
// If it exist, check if it's a directory
return (($path !== false) && is_dir($path)) ? $path : false;
-} \ No newline at end of file
+}
diff --git a/include/zot.php b/include/zot.php
index 0cdf7fc87..9d9f9ab5f 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -4048,6 +4048,17 @@ function delivery_report_is_storable($dr) {
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient_not_found'))
return false;
+ // If you have a private post with a recipient list, every single site is going to report
+ // back a failed delivery for anybody on that list that isn't local to them. We're only
+ // concerned about this if we have a local hubloc record which says we expected them to
+ // have a channel on that site.
+
+ $r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_url = '%s'",
+ dbesc($rxchan),
+ dbesc($dr['location'])
+ );
+ if((! $r) && ($dr['status'] === 'recipient_not_found'))
+ return false;
$r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc($rxchan),
diff --git a/install/schema_mysql.sql b/install/schema_mysql.sql
index 01cf97674..c36bfaa57 100644
--- a/install/schema_mysql.sql
+++ b/install/schema_mysql.sql
@@ -517,8 +517,10 @@ CREATE TABLE IF NOT EXISTS `hook` (
`file` char(255) NOT NULL DEFAULT '',
`function` char(255) NOT NULL DEFAULT '',
`priority` int(11) unsigned NOT NULL DEFAULT '0',
+ `hook_version` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
- KEY `hook` (`hook`)
+ KEY `hook` (`hook`),
+ KEY `hook_version` (`hook_version`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `hubloc` (
diff --git a/install/schema_postgres.sql b/install/schema_postgres.sql
index a7cd5875c..d4bb54b1e 100644
--- a/install/schema_postgres.sql
+++ b/install/schema_postgres.sql
@@ -512,10 +512,12 @@ CREATE TABLE "hook" (
"file" text NOT NULL,
"function" text NOT NULL,
"priority" bigint NOT NULL DEFAULT '0',
+ "hook_version" smallint NOT NULL DEFAULT '0',
PRIMARY KEY ("id")
);
create index "hook_idx" on hook ("hook");
+create index "hook_version_idx" on hook ("hook_version");
CREATE TABLE "hubloc" (
"hubloc_id" serial NOT NULL,
"hubloc_guid" text NOT NULL DEFAULT '',
diff --git a/install/update.php b/install/update.php
index bfd01494f..2dc4a6db3 100644
--- a/install/update.php
+++ b/install/update.php
@@ -1,6 +1,6 @@
<?php
-define( 'UPDATE_VERSION' , 1165 );
+define( 'UPDATE_VERSION' , 1166 );
/**
*
@@ -2058,3 +2058,16 @@ function update_r1164() {
return UPDATE_FAILED;
}
+function update_r1165() {
+
+ $r1 = q("alter table hook add hook_version int not null default '0' ");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES)
+ $r2 = q("create index \"hook_version_idx\" on hook (\"hook_version\") ");
+ else
+ $r2 = q("alter table hook add index ( hook_version ) ");
+ if($r1 && $r2)
+ return UPDATE_SUCCESS;
+ return UPDATE_FAILED;
+}
+
diff --git a/mod/_well_known.php b/mod/_well_known.php
deleted file mode 100644
index 23d79bb1d..000000000
--- a/mod/_well_known.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-
-function _well_known_init(&$a){
-
- if(argc() > 1) {
-
- $arr = array('server' => $_SERVER, 'request' => $_REQUEST);
- call_hooks('well_known', $arr);
-
-
- if(! check_siteallowed($_SERVER['REMOTE_ADDR'])) {
- logger('well_known: site not allowed. ' . $_SERVER['REMOTE_ADDR']);
- killme();
- }
-
- // from php.net re: REMOTE_HOST:
- // Note: Your web server must be configured to create this variable. For example in Apache
- // you'll need HostnameLookups On inside httpd.conf for it to exist. See also gethostbyaddr().
-
- if(get_config('system','siteallowed_remote_host') && (! check_siteallowed($_SERVER['REMOTE_HOST']))) {
- logger('well_known: site not allowed. ' . $_SERVER['REMOTE_HOST']);
- killme();
- }
-
-
- switch(argv(1)) {
- case 'zot-info':
- App::$argc -= 1;
- array_shift(App::$argv);
- App::$argv[0] = 'zfinger';
- require_once('mod/zfinger.php');
- zfinger_init($a);
- break;
-
- case 'webfinger':
- App::$argc -= 1;
- array_shift(App::$argv);
- App::$argv[0] = 'wfinger';
- require_once('mod/wfinger.php');
- wfinger_init($a);
- break;
-
- case 'host-meta':
- App::$argc -= 1;
- array_shift(App::$argv);
- App::$argv[0] = 'hostxrd';
- require_once('mod/hostxrd.php');
- hostxrd_init($a);
- break;
-
- default:
- if(file_exists(App::$cmd)) {
- echo file_get_contents(App::$cmd);
- killme();
- }
- elseif(file_exists(App::$cmd . '.php'))
- require_once(App::$cmd . '.php');
- break;
-
- }
- }
-
- http_status_exit(404);
-} \ No newline at end of file
diff --git a/mod/achievements.php b/mod/achievements.php
deleted file mode 100644
index 9d4dad35b..000000000
--- a/mod/achievements.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-
-function achievements_content(&$a) {
- // 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
-));
-
-}
diff --git a/mod/acl.php b/mod/acl.php
deleted file mode 100644
index 146cb74c8..000000000
--- a/mod/acl.php
+++ /dev/null
@@ -1,308 +0,0 @@
-<?php
-
-/* ACL selector json backend */
-require_once("include/acl_selectors.php");
-require_once("include/group.php");
-
-function acl_init(&$a){
-
-// 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 = 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();
-}
diff --git a/mod/admin.php b/mod/admin.php
deleted file mode 100644
index be703f922..000000000
--- a/mod/admin.php
+++ /dev/null
@@ -1,1776 +0,0 @@
-<?php
-/**
- * @file mod/admin.php
- * @brief Hubzilla's admin controller.
- *
- * Controller for the /admin/ area.
- */
-
-require_once('include/queue_fn.php');
-require_once('include/account.php');
-
-/**
- * @param App &$a
- */
-function admin_post(&$a){
- logger('admin_post', LOGGER_DEBUG);
-
- if(! is_site_admin()) {
- return;
- }
-
- // urls
- if (argc() > 1) {
- switch (argv(1)) {
- case 'site':
- admin_page_site_post($a);
- break;
- case 'users':
- admin_page_users_post($a);
- break;
- case 'channels':
- admin_page_channels_post($a);
- break;
- case 'plugins':
- if (argc() > 2 &&
- is_file("addon/" . argv(2) . "/" . argv(2) . ".php")){
- @include_once("addon/" . argv(2) . "/" . argv(2) . ".php");
- if(function_exists(argv(2).'_plugin_admin_post')) {
- $func = argv(2) . '_plugin_admin_post';
- $func($a);
- }
- }
- goaway(z_root() . '/admin/plugins/' . argv(2) );
- break;
- case 'themes':
- $theme = argv(2);
- if (is_file("view/theme/$theme/php/config.php")){
- require_once("view/theme/$theme/php/config.php");
-// fixme add parent theme if derived
- if (function_exists("theme_admin_post")){
- theme_admin_post($a);
- }
- }
- info(t('Theme settings updated.'));
- if(is_ajax()) return;
-
- goaway(z_root() . '/admin/themes/' . $theme );
- break;
- case 'logs':
- admin_page_logs_post($a);
- break;
- case 'hubloc':
- admin_page_hubloc_post($a);
- break;
- case 'security':
- admin_page_security_post($a);
- break;
- case 'features':
- admin_page_features_post($a);
- break;
- case 'dbsync':
- admin_page_dbsync_post($a);
- break;
- case 'profs':
- admin_page_profs_post($a);
- break;
- }
- }
-
- goaway(z_root() . '/admin' );
-}
-
-/**
- * @param App &$a
- * @return string
- */
-function admin_content(&$a) {
-
- logger('admin_content', LOGGER_DEBUG);
-
- if(! is_site_admin()) {
- return login(false);
- }
-
-
- /*
- * Page content
- */
- $o = '';
-
- // urls
- if (argc() > 1){
- switch (argv(1)) {
- case 'site':
- $o = admin_page_site($a);
- break;
- case 'users':
- $o = admin_page_users($a);
- break;
- case 'channels':
- $o = admin_page_channels($a);
- break;
- case 'plugins':
- $o = admin_page_plugins($a);
- break;
- case 'themes':
- $o = admin_page_themes($a);
- break;
-// case 'hubloc':
-// $o = admin_page_hubloc($a);
-// break;
- case 'security':
- $o = admin_page_security($a);
- break;
- case 'features':
- $o = admin_page_features($a);
- break;
- case 'logs':
- $o = admin_page_logs($a);
- break;
- case 'dbsync':
- $o = admin_page_dbsync($a);
- break;
- case 'profs':
- $o = admin_page_profs($a);
- break;
- case 'queue':
- $o = admin_page_queue($a);
- break;
- default:
- notice( t('Item not found.') );
- }
- } else {
- $o = admin_page_summary($a);
- }
-
- if(is_ajax()) {
- echo $o;
- killme();
- return '';
- } else {
- return $o;
- }
-}
-
-
-/**
- * @brief Returns content for Admin Summary Page.
- *
- * @param App &$a
- * @return string HTML from parsed admin_summary.tpl
- */
-function admin_page_summary(&$a) {
-
- // list total user accounts, expirations etc.
- $accounts = array();
- $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires != '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account",
- db_utcnow(),
- db_utcnow(),
- dbesc(NULL_DATE),
- intval(ACCOUNT_BLOCKED)
- );
- if ($r) {
- $accounts['total'] = array('label' => t('# Accounts'), 'val' => $r[0]['total']);
- $accounts['blocked'] = array('label' => t('# blocked accounts'), 'val' => $r[0]['blocked']);
- $accounts['expired'] = array('label' => t('# expired accounts'), 'val' => $r[0]['expired']);
- $accounts['expiring'] = array('label' => t('# expiring accounts'), 'val' => $r[0]['expiring']);
- }
-
- // pending registrations
- $r = q("SELECT COUNT(id) AS `count` FROM `register` WHERE `uid` != '0'");
- $pending = $r[0]['count'];
-
- // available channels, primary and clones
- $channels = array();
- $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0");
- if ($r) {
- $channels['total'] = array('label' => t('# Channels'), 'val' => $r[0]['total']);
- $channels['main'] = array('label' => t('# primary'), 'val' => $r[0]['main']);
- $channels['clones'] = array('label' => t('# clones'), 'val' => $r[0]['clones']);
- }
-
- // We can do better, but this is a quick queue status
- $r = q("SELECT COUNT(outq_delivered) AS total FROM outq WHERE outq_delivered = 0");
- $queue = (($r) ? $r[0]['total'] : 0);
- $queues = array( 'label' => t('Message queues'), 'queue' => $queue );
-
- // If no plugins active return 0, otherwise list of plugin names
- $plugins = (count(App::$plugins) == 0) ? count(App::$plugins) : App::$plugins;
-
- // Could be extended to provide also other alerts to the admin
- $alertmsg = '';
- // annoy admin about upcoming unsupported PHP version
- if (version_compare(PHP_VERSION, '5.4', '<')) {
- $alertmsg = 'Your PHP version ' . PHP_VERSION . ' will not be supported with the next major release of $Projectname. You are strongly urged to upgrade to a current version.'
- . '<br>PHP 5.3 has reached its <a href="http://php.net/eol.php" class="alert-link">End of Life (EOL)</a> in August 2014.'
- . ' A list about current PHP versions can be found <a href="http://php.net/supported-versions.php" class="alert-link">here</a>.';
- }
-
- $t = get_markup_template('admin_summary.tpl');
- return replace_macros($t, array(
- '$title' => t('Administration'),
- '$page' => t('Summary'),
- '$adminalertmsg' => $alertmsg,
- '$queues' => $queues,
- '$accounts' => array( t('Registered accounts'), $accounts),
- '$pending' => array( t('Pending registrations'), $pending),
- '$channels' => array( t('Registered channels'), $channels),
- '$plugins' => array( t('Active plugins'), $plugins ),
- '$version' => array( t('Version'), RED_VERSION),
- '$build' => get_config('system', 'db_version')
- ));
-}
-
-
-/**
- * @brief POST handler for Admin Site Page.
- *
- * @param App &$a
- */
-function admin_page_site_post(&$a){
- if (!x($_POST, 'page_site')){
- return;
- }
-
- check_form_security_token_redirectOnErr('/admin/site', 'admin_site');
-
- $sitename = ((x($_POST,'sitename')) ? notags(trim($_POST['sitename'])) : '');
- $banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false);
- $admininfo = ((x($_POST,'admininfo')) ? trim($_POST['admininfo']) : false);
- $language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : '');
- $theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : '');
- $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : '');
-// $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : '');
- $maximagesize = ((x($_POST,'maximagesize')) ? intval(trim($_POST['maximagesize'])) : 0);
-
- $register_policy = ((x($_POST,'register_policy')) ? intval(trim($_POST['register_policy'])) : 0);
-
- $access_policy = ((x($_POST,'access_policy')) ? intval(trim($_POST['access_policy'])) : 0);
- $invite_only = ((x($_POST,'invite_only')) ? True : False);
- $abandon_days = ((x($_POST,'abandon_days')) ? intval(trim($_POST['abandon_days'])) : 0);
-
- $register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : '');
- $frontpage = ((x($_POST,'frontpage')) ? notags(trim($_POST['frontpage'])) : '');
- $mirror_frontpage = ((x($_POST,'mirror_frontpage')) ? intval(trim($_POST['mirror_frontpage'])) : 0);
- $directory_server = ((x($_POST,'directory_server')) ? trim($_POST['directory_server']) : '');
- $allowed_sites = ((x($_POST,'allowed_sites')) ? notags(trim($_POST['allowed_sites'])) : '');
- $allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : '');
- $not_allowed_email = ((x($_POST,'not_allowed_email')) ? notags(trim($_POST['not_allowed_email'])) : '');
- $force_publish = ((x($_POST,'publish_all')) ? True : False);
- $disable_discover_tab = ((x($_POST,'disable_discover_tab')) ? False : True);
- $login_on_homepage = ((x($_POST,'login_on_homepage')) ? True : False);
- $global_directory = ((x($_POST,'directory_submit_url')) ? notags(trim($_POST['directory_submit_url'])) : '');
- $no_community_page = !((x($_POST,'no_community_page')) ? True : False);
- $default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0);
-
- $verifyssl = ((x($_POST,'verifyssl')) ? True : False);
- $proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
- $proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
- $timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60);
- $delivery_interval = ((x($_POST,'delivery_interval'))? intval(trim($_POST['delivery_interval'])) : 0);
- $delivery_batch_count = ((x($_POST,'delivery_batch_count') && $_POST['delivery_batch_count'] > 0)? intval(trim($_POST['delivery_batch_count'])) : 1);
- $poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0);
- $maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
- $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
- $verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
-
- set_config('system', 'feed_contacts', $feed_contacts);
- set_config('system', 'delivery_interval', $delivery_interval);
- set_config('system', 'delivery_batch_count', $delivery_batch_count);
- set_config('system', 'poll_interval', $poll_interval);
- set_config('system', 'maxloadavg', $maxloadavg);
- set_config('system', 'frontpage', $frontpage);
- set_config('system', 'mirror_frontpage', $mirror_frontpage);
- set_config('system', 'sitename', $sitename);
- set_config('system', 'login_on_homepage', $login_on_homepage);
- set_config('system', 'verify_email', $verify_email);
- set_config('system', 'default_expire_days', $default_expire_days);
-
- if($directory_server)
- set_config('system','directory_server',$directory_server);
-
- if ($banner == '') {
- del_config('system', 'banner');
- } else {
- set_config('system', 'banner', $banner);
- }
-
- if ($admininfo == ''){
- del_config('system', 'admininfo');
- } else {
- require_once('include/text.php');
- linkify_tags($a, $admininfo, local_channel());
- set_config('system', 'admininfo', $admininfo);
- }
- set_config('system', 'language', $language);
- set_config('system', 'theme', $theme);
- if ( $theme_mobile === '---' ) {
- del_config('system', 'mobile_theme');
- } else {
- set_config('system', 'mobile_theme', $theme_mobile);
- }
-// set_config('system','site_channel', $site_channel);
- set_config('system','maximagesize', $maximagesize);
-
- set_config('system','register_policy', $register_policy);
- set_config('system','invitation_only', $invite_only);
- set_config('system','access_policy', $access_policy);
- set_config('system','account_abandon_days', $abandon_days);
- set_config('system','register_text', $register_text);
- set_config('system','allowed_sites', $allowed_sites);
- set_config('system','allowed_email', $allowed_email);
- set_config('system','not_allowed_email', $not_allowed_email);
- set_config('system','publish_all', $force_publish);
- set_config('system','disable_discover_tab', $disable_discover_tab);
- if ($global_directory == '') {
- del_config('system', 'directory_submit_url');
- } else {
- set_config('system', 'directory_submit_url', $global_directory);
- }
-
- set_config('system','no_community_page', $no_community_page);
- set_config('system','no_utf', $no_utf);
- set_config('system','verifyssl', $verifyssl);
- set_config('system','proxyuser', $proxyuser);
- set_config('system','proxy', $proxy);
- set_config('system','curl_timeout', $timeout);
-
- info( t('Site settings updated.') . EOL);
- goaway(z_root() . '/admin/site' );
-}
-
-/**
- * @brief Admin page site.
- *
- * @param App $a
- * @return string
- */
-function admin_page_site(&$a) {
-
- /* Installed langs */
- $lang_choices = array();
- $langs = glob('view/*/hstrings.php');
-
- if(is_array($langs) && count($langs)) {
- if(! in_array('view/en/hstrings.php',$langs))
- $langs[] = 'view/en/';
- asort($langs);
- foreach($langs as $l) {
- $t = explode("/",$l);
- $lang_choices[$t[1]] = $t[1];
- }
- }
-
- /* Installed themes */
- $theme_choices_mobile["---"] = t("Default");
- $theme_choices = array();
- $files = glob('view/theme/*');
- if($files) {
- foreach($files as $file) {
- $vars = '';
- $f = basename($file);
- if (file_exists($file . '/library'))
- continue;
- if (file_exists($file . '/mobile'))
- $vars = t('mobile');
- if (file_exists($file . '/experimental'))
- $vars .= t('experimental');
- if (file_exists($file . '/unsupported'))
- $vars .= t('unsupported');
- if ($vars) {
- $theme_choices[$f] = $f . ' (' . $vars . ')';
- $theme_choices_mobile[$f] = $f . ' (' . $vars . ')';
- }
- else {
- $theme_choices[$f] = $f;
- $theme_choices_mobile[$f] = $f;
- }
- }
- }
-
- $dir_choices = null;
- $dirmode = get_config('system','directory_mode');
- $realm = get_directory_realm();
-
- // directory server should not be set or settable unless we are a directory client
-
- if($dirmode == DIRECTORY_MODE_NORMAL) {
- $x = q("select site_url from site where site_flags in (%d,%d) and site_realm = '%s'",
- intval(DIRECTORY_MODE_SECONDARY),
- intval(DIRECTORY_MODE_PRIMARY),
- dbesc($realm)
- );
- if($x) {
- $dir_choices = array();
- foreach($x as $xx) {
- $dir_choices[$xx['site_url']] = $xx['site_url'];
- }
- }
- }
-
- /* Banner */
-
- $banner = get_config('system', 'banner');
- if($banner === false)
- $banner = get_config('system','sitename');
-
- $banner = htmlspecialchars($banner);
-
- /* Admin Info */
- $admininfo = get_config('system', 'admininfo');
-
- /* Register policy */
- $register_choices = Array(
- REGISTER_CLOSED => t("No"),
- REGISTER_APPROVE => t("Yes - with approval"),
- REGISTER_OPEN => t("Yes")
- );
-
- /* Acess policy */
- $access_choices = Array(
- ACCESS_PRIVATE => t("My site is not a public server"),
- ACCESS_PAID => t("My site has paid access only"),
- ACCESS_FREE => t("My site has free access only"),
- ACCESS_TIERED => t("My site offers free accounts with optional paid upgrades")
- );
-
-// $ssl_choices = array(
-// SSL_POLICY_NONE => t("No SSL policy, links will track page SSL state"),
-// SSL_POLICY_FULL => t("Force all links to use SSL")
-// );
-
- $discover_tab = get_config('system','disable_discover_tab');
- // $disable public streams by default
- if($discover_tab === false)
- $discover_tab = 1;
- // now invert the logic for the setting.
- $discover_tab = (1 - $discover_tab);
-
-
- $homelogin = get_config('system','login_on_homepage');
-
- $t = get_markup_template("admin_site.tpl");
- return replace_macros($t, array(
- '$title' => t('Administration'),
- '$page' => t('Site'),
- '$submit' => t('Submit'),
- '$registration' => t('Registration'),
- '$upload' => t('File upload'),
- '$corporate' => t('Policies'),
- '$advanced' => t('Advanced'),
-
- '$baseurl' => z_root(),
- // name, label, value, help string, extra data...
- '$sitename' => array('sitename', t("Site name"), htmlspecialchars(get_config('system','sitename'), ENT_QUOTES, 'UTF-8'),''),
- '$banner' => array('banner', t("Banner/Logo"), $banner, ""),
- '$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")),
- '$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
- '$theme' => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices),
- '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile),
-// '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")),
- '$feed_contacts' => array('feed_contacts', t('Allow Feeds as Connections'),get_config('system','feed_contacts'),t('(Heavy system resource usage)')),
- '$maximagesize' => array('maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.")),
- '$register_policy' => array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices),
- '$invite_only' => array('invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. Above register policy must be set to Yes.")),
- '$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), "This is displayed on the public server site list.", $access_choices),
- '$register_text' => array('register_text', t("Register text"), htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")),
- '$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'public' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")),
- '$mirror_frontpage' => array('mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting')),
- '$abandon_days' => array('abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')),
- '$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")),
- '$allowed_email' => array('allowed_email', t("Allowed email domains"), get_config('system','allowed_email'), t("Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains")),
- '$not_allowed_email' => array('not_allowed_email', t("Not allowed email domains"), get_config('system','not_allowed_email'), t("Comma separated list of domains which are not allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains, unless allowed domains have been defined.")),
- '$verify_email' => array('verify_email', t("Verify Email Addresses"), get_config('system','verify_email'), t("Check to verify email addresses used in account registration (recommended).")),
- '$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")),
- '$disable_discover_tab' => array('disable_discover_tab', t('Import Public Streams'), $discover_tab, t('Import and allow access to public content pulled from other sites. Warning: this content is unmoderated.')),
- '$login_on_homepage' => array('login_on_homepage', t("login on Homepage"),((intval($homelogin) || $homelogin === false) ? 1 : '') , t("Present a login box to visitors on the home page if no other content has been configured.")),
-
- '$directory_server' => (($dir_choices) ? array('directory_server', t("Directory Server URL"), get_config('system','directory_server'), t("Default directory server"), $dir_choices) : null),
-
- '$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
- '$proxy' => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
- '$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
- '$delivery_interval' => array('delivery_interval', t("Delivery interval"), (x(get_config('system','delivery_interval'))?get_config('system','delivery_interval'):2), t("Delay background delivery processes by this many seconds to reduce system load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 for large dedicated servers.")),
- '$delivery_batch_count' => array('delivery_batch_count', t('Deliveries per process'),(x(get_config('system','delivery_batch_count'))?get_config('system','delivery_batch_count'):1), t("Number of deliveries to attempt in a single operating system process. Adjust if necessary to tune system performance. Recommend: 1-5.")),
- '$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
- '$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
- '$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
- '$form_security_token' => get_form_security_token("admin_site"),
- ));
-}
-
-function admin_page_hubloc_post(&$a){
- check_form_security_token_redirectOnErr('/admin/hubloc', 'admin_hubloc');
- require_once('include/zot.php');
-
- //prepare for ping
-
- if ( $_POST['hublocid']) {
- $hublocid = $_POST['hublocid'];
- $arrhublocurl = q("SELECT hubloc_url FROM hubloc WHERE hubloc_id = %d ",
- intval($hublocid)
- );
- $hublocurl = $arrhublocurl[0]['hubloc_url'] . '/post';
-
- //perform ping
- $m = zot_build_packet(App::get_channel(),'ping');
- $r = zot_zot($hublocurl,$m);
- //handle results and set the hubloc flags in db to make results visible
- $r2 = $r['body'];
- $r3 = $r2['success'];
- if ( $r3['success'] == True ){
- //set HUBLOC_OFFLINE to 0
- logger(' success = true ',LOGGER_DEBUG);
- } else {
- //set HUBLOC_OFFLINE to 1
- logger(' success = false ', LOGGER_DEBUG);
- }
-
- //unfotunatly zping wont work, I guess return format is not correct
- //require_once('mod/zping.php');
- //$r = zping_content($hublocurl);
- //logger('zping answer: ' . $r, LOGGER_DEBUG);
-
- //in case of repair store new pub key for tested hubloc (all channel with this hubloc) in db
- //after repair set hubloc flags to 0
- }
-
- goaway(z_root() . '/admin/hubloc' );
-}
-
-function trim_array_elems($arr) {
- $narr = array();
-
- if($arr && is_array($arr)) {
- for($x = 0; $x < count($arr); $x ++) {
- $y = trim($arr[$x]);
- if($y)
- $narr[] = $y;
- }
- }
- return $narr;
-}
-
-function admin_page_security_post(&$a){
- check_form_security_token_redirectOnErr('/admin/security', 'admin_security');
-
-logger('post: ' . print_r($_POST,true));
-
- $block_public = ((x($_POST,'block_public')) ? True : False);
- set_config('system','block_public',$block_public);
-
- $ws = trim_array_elems(explode("\n",$_POST['whitelisted_sites']));
- set_config('system','whitelisted_sites',$ws);
-
- $bs = trim_array_elems(explode("\n",$_POST['blacklisted_sites']));
- set_config('system','blacklisted_sites',$bs);
-
- $wc = trim_array_elems(explode("\n",$_POST['whitelisted_channels']));
- set_config('system','whitelisted_channels',$wc);
-
- $bc = trim_array_elems(explode("\n",$_POST['blacklisted_channels']));
- set_config('system','blacklisted_channels',$bc);
-
- $embed_coop = ((x($_POST,'embed_coop')) ? True : False);
- set_config('system','embed_coop',$embed_coop);
-
- $we = trim_array_elems(explode("\n",$_POST['embed_allow']));
- set_config('system','embed_allow',$we);
-
- $be = trim_array_elems(explode("\n",$_POST['embed_deny']));
- set_config('system','embed_deny',$be);
-
- goaway(z_root() . '/admin/security');
-}
-
-
-
-
-function admin_page_features_post(&$a) {
-
- check_form_security_token_redirectOnErr('/admin/features', 'admin_manage_features');
-
- logger('postvars: ' . print_r($_POST,true));
-
- $arr = array();
- $features = get_features(false);
-
- foreach($features as $fname => $fdata) {
- foreach(array_slice($fdata,1) as $f) {
- $feature = $f[0];
-
- if(array_key_exists('feature_' . $feature,$_POST))
- $val = intval($_POST['feature_' . $feature]);
- else
- $val = 0;
- set_config('feature',$feature,$val);
-
- if(array_key_exists('featurelock_' . $feature,$_POST))
- set_config('feature_lock',$feature,$val);
- else
- del_config('feature_lock',$feature);
- }
- }
-
- goaway(z_root() . '/admin/features' );
-
-}
-
-function admin_page_features(&$a) {
-
- if((argc() > 1) && (argv(1) === 'features')) {
- $arr = array();
- $features = get_features(false);
-
- foreach($features as $fname => $fdata) {
- $arr[$fname] = array();
- $arr[$fname][0] = $fdata[0];
- foreach(array_slice($fdata,1) as $f) {
-
- $set = get_config('feature',$f[0]);
- if($set === false)
- $set = $f[3];
- $arr[$fname][1][] = array(
- array('feature_' .$f[0],$f[1],$set,$f[2],array(t('Off'),t('On'))),
- array('featurelock_' .$f[0],sprintf( t('Lock feature %s'),$f[1]),(($f[4] !== false) ? 1 : 0),'',array(t('Off'),t('On')))
- );
- }
- }
-
- $tpl = get_markup_template("admin_settings_features.tpl");
- $o .= replace_macros($tpl, array(
- '$form_security_token' => get_form_security_token("admin_manage_features"),
- '$title' => t('Manage Additional Features'),
- '$features' => $arr,
- '$submit' => t('Submit'),
- ));
-
- return $o;
- }
-}
-
-
-
-
-
-function admin_page_hubloc(&$a) {
- $hubloc = q("SELECT hubloc_id, hubloc_addr, hubloc_host, hubloc_status FROM hubloc");
-
- if(! $hubloc){
- notice( t('No server found') . EOL);
- goaway(z_root() . '/admin/hubloc');
- }
-
- $t = get_markup_template('admin_hubloc.tpl');
- return replace_macros($t, array(
- '$hubloc' => $hubloc,
- '$th_hubloc' => array(t('ID'), t('for channel'), t('on server'), t('Status')),
- '$title' => t('Administration'),
- '$page' => t('Server'),
- '$queues' => $queues,
- //'$accounts' => $accounts, /*$accounts is empty here*/
- '$pending' => array( t('Pending registrations'), $pending),
- '$plugins' => array( t('Active plugins'), App::$plugins ),
- '$form_security_token' => get_form_security_token('admin_hubloc')
- ));
-}
-
-function admin_page_security(&$a) {
-
- $whitesites = get_config('system','whitelisted_sites');
- $whitesites_str = ((is_array($whitesites)) ? implode($whitesites,"\n") : '');
-
- $blacksites = get_config('system','blacklisted_sites');
- $blacksites_str = ((is_array($blacksites)) ? implode($blacksites,"\n") : '');
-
-
- $whitechannels = get_config('system','whitelisted_channels');
- $whitechannels_str = ((is_array($whitechannels)) ? implode($whitechannels,"\n") : '');
-
- $blackchannels = get_config('system','blacklisted_channels');
- $blackchannels_str = ((is_array($blackchannels)) ? implode($blackchannels,"\n") : '');
-
-
- $whiteembeds = get_config('system','embed_allow');
- $whiteembeds_str = ((is_array($whiteembeds)) ? implode($whiteembeds,"\n") : '');
-
- $blackembeds = get_config('system','embed_deny');
- $blackembeds_str = ((is_array($blackembeds)) ? implode($blackembeds,"\n") : '');
-
- $embed_coop = intval(get_config('system','embed_coop'));
-
-// wait to implement this until we have a co-op in place.
-// if((! $whiteembeds) && (! $blackembeds) && (! $embed_coop))
-// $whiteembeds_str = "youtube.com\nyoutu.be\ntwitter.com\nvimeo.com\nsoundcloud.com\nwikipedia.com";
-
- $t = get_markup_template('admin_security.tpl');
- return replace_macros($t, array(
- '$title' => t('Administration'),
- '$page' => t('Security'),
- '$form_security_token' => get_form_security_token('admin_security'),
- '$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently authenticated.")),
- '$whitelisted_sites' => array('whitelisted_sites', t('Allow communications only from these sites'), $whitesites_str, t('One site per line. Leave empty to allow communication from anywhere by default')),
- '$blacklisted_sites' => array('blacklisted_sites', t('Block communications from these sites'), $blacksites_str, ''),
- '$whitelisted_channels' => array('whitelisted_channels', t('Allow communications only from these channels'), $whitechannels_str, t('One channel (hash) per line. Leave empty to allow from any channel by default')),
- '$blacklisted_channels' => array('blacklisted_channels', t('Block communications from these channels'), $blackchannels_str, ''),
- '$embed_allow' => array('embed_allow', t('Allow embedded HTML content only from these domains'), $whiteembeds_str, t('One site per line. Leave empty to allow from any site by default')),
- '$embed_deny' => array('embed_deny', t('Block embedded HTML from these domains'), $blackembeds_str, ''),
-
- '$embed_coop' => array('embed_coop', t('Cooperative embed security'), $embed_coop, t('Enable to share embed security with other compatible sites/hubs')),
- '$submit' => t('Submit')
- ));
-}
-
-
-
-
-function admin_page_dbsync(&$a) {
- $o = '';
-
- if(argc() > 3 && intval(argv(3)) && argv(2) === 'mark') {
- set_config('database', 'update_r' . intval(argv(3)), 'success');
- if(intval(get_config('system','db_version')) <= intval(argv(3)))
- set_config('system','db_version',intval(argv(3)) + 1);
- info( t('Update has been marked successful') . EOL);
- goaway(z_root() . '/admin/dbsync');
- }
-
- if(argc() > 2 && intval(argv(2))) {
- require_once('install/update.php');
- $func = 'update_r' . intval(argv(2));
- if(function_exists($func)) {
- $retval = $func();
- if($retval === UPDATE_FAILED) {
- $o .= sprintf( t('Executing %s failed. Check system logs.'), $func);
- }
- elseif($retval === UPDATE_SUCCESS) {
- $o .= sprintf( t('Update %s was successfully applied.'), $func);
- set_config('database',$func, 'success');
- }
- else
- $o .= sprintf( t('Update %s did not return a status. Unknown if it succeeded.'), $func);
- }
- else
- $o .= sprintf( t('Update function %s could not be found.'), $func);
-
- return $o;
- }
-
- $failed = array();
- $r = q("select * from config where `cat` = 'database' ");
- if(count($r)) {
- foreach($r as $rr) {
- $upd = intval(substr($rr['k'],8));
- if($rr['v'] === 'success')
- continue;
- $failed[] = $upd;
- }
- }
- if(! count($failed))
- return '<div class="generic-content-wrapper-styled"><h3>' . t('No failed updates.') . '</h3></div>';
-
- $o = replace_macros(get_markup_template('failed_updates.tpl'),array(
- '$base' => z_root(),
- '$banner' => t('Failed Updates'),
- '$desc' => '',
- '$mark' => t('Mark success (if update was manually applied)'),
- '$apply' => t('Attempt to execute this update step automatically'),
- '$failed' => $failed
- ));
-
- return $o;
-}
-
-function admin_page_queue($a) {
- $o = '';
-
- $expert = ((array_key_exists('expert',$_REQUEST)) ? intval($_REQUEST['expert']) : 0);
-
- if($_REQUEST['drophub']) {
- require_once('hubloc.php');
- hubloc_mark_as_down($_REQUEST['drophub']);
- remove_queue_by_posturl($_REQUEST['drophub']);
- }
-
- if($_REQUEST['emptyhub']) {
- remove_queue_by_posturl($_REQUEST['emptyhub']);
- }
-
- $r = q("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq
- where outq_delivered = 0 group by outq_posturl order by total desc");
-
- for($x = 0; $x < count($r); $x ++) {
- $r[$x]['eurl'] = urlencode($r[$x]['outq_posturl']);
- $r[$x]['connected'] = datetime_convert('UTC',date_default_timezone_get(),$r[$x]['connected'],'Y-m-d');
- }
-
- $o = replace_macros(get_markup_template('admin_queue.tpl'), array(
- '$banner' => t('Queue Statistics'),
- '$numentries' => t('Total Entries'),
- '$priority' => t('Priority'),
- '$desturl' => t('Destination URL'),
- '$nukehub' => t('Mark hub permanently offline'),
- '$empty' => t('Empty queue for this hub'),
- '$lastconn' => t('Last known contact'),
- '$hasentries' => ((count($r)) ? true : false),
- '$entries' => $r,
- '$expert' => $expert
- ));
-
- return $o;
-}
-
-/**
- * @brief Handle POST actions on users admin page.
- *
- * This function is called when on the admin user/account page the form was
- * submitted to handle multiple operations at once. If one of the icons next
- * to an entry are pressed the function admin_page_users() will handle this.
- *
- * @param App $a
- */
-function admin_page_users_post($a) {
- $pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() );
- $users = ( x($_POST, 'user') ? $_POST['user'] : array() );
- $blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : array() );
-
- check_form_security_token_redirectOnErr('/admin/users', 'admin_users');
-
- // change to switch structure?
- // account block/unblock button was submitted
- if (x($_POST, 'page_users_block')) {
- for ($i = 0; $i < count($users); $i++) {
- // if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
- $op = ($blocked[$i]) ? '& ~' : '| ';
- q("UPDATE account SET account_flags = (account_flags $op%d) WHERE account_id = %d",
- intval(ACCOUNT_BLOCKED),
- intval($users[$i])
- );
- }
- notice( sprintf( tt("%s account blocked/unblocked", "%s account blocked/unblocked", count($users)), count($users)) );
- }
- // account delete button was submitted
- if (x($_POST, 'page_users_delete')) {
- require_once('include/Contact.php');
- foreach ($users as $uid){
- account_remove($uid, true, false);
- }
- notice( sprintf( tt("%s account deleted", "%s accounts deleted", count($users)), count($users)) );
- }
- // registration approved button was submitted
- if (x($_POST, 'page_users_approve')) {
- foreach ($pending as $hash) {
- account_allow($hash);
- }
- }
- // registration deny button was submitted
- if (x($_POST, 'page_users_deny')) {
- foreach ($pending as $hash) {
- account_deny($hash);
- }
- }
-
- goaway(z_root() . '/admin/users' );
-}
-
-/**
- * @brief Generate users admin page and handle single item operations.
- *
- * This function generates the users/account admin page and handles the actions
- * if an icon next to an entry was clicked. If several items were selected and
- * the form was submitted it is handled by the function admin_page_users_post().
- *
- * @param App &$a
- * @return string
- */
-function admin_page_users(&$a){
- if (argc() > 2) {
- $uid = argv(3);
- $account = q("SELECT * FROM account WHERE account_id = %d",
- intval($uid)
- );
-
- if (! $account) {
- notice( t('Account not found') . EOL);
- goaway(z_root() . '/admin/users' );
- }
-
- check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
-
- switch (argv(2)){
- case 'delete':
- // delete user
- require_once('include/Contact.php');
- account_remove($uid,true,false);
-
- notice( sprintf(t("Account '%s' deleted"), $account[0]['account_email']) . EOL);
- break;
- case 'block':
- q("UPDATE account SET account_flags = ( account_flags | %d ) WHERE account_id = %d",
- intval(ACCOUNT_BLOCKED),
- intval($uid)
- );
-
- notice( sprintf( t("Account '%s' blocked") , $account[0]['account_email']) . EOL);
- break;
- case 'unblock':
- q("UPDATE account SET account_flags = ( account_flags & ~%d ) WHERE account_id = %d",
- intval(ACCOUNT_BLOCKED),
- intval($uid)
- );
-
- notice( sprintf( t("Account '%s' unblocked"), $account[0]['account_email']) . EOL);
- break;
- }
-
- goaway(z_root() . '/admin/users' );
- }
-
- /* get pending */
- $pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d )>0 ",
- intval(ACCOUNT_PENDING)
- );
-
- /* get users */
-
- $total = q("SELECT count(*) as total FROM account");
- if (count($total)) {
- App::set_pager_total($total[0]['total']);
- App::set_pager_itemspage(100);
- }
-
-
-// We'll still need to link email addresses to admin/users/channels or some such, but this bit doesn't exist yet.
-// That's where we need to be doing last post/channel flags/etc, not here.
-
- $serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : '');
-
- $order = " order by account_email asc ";
- if($_REQUEST['order'] === 'expires')
- $order = " order by account_expires desc ";
- if($_REQUEST['order'] === 'created')
- $order = " order by account_created desc ";
-
- $users = q("SELECT `account_id` , `account_email`, `account_lastlog`, `account_created`, `account_expires`, " . "`account_service_class`, ( account_flags & %d )>0 as `blocked`, " .
- "(SELECT %s FROM channel as ch " .
- "WHERE ch.channel_account_id = ac.account_id and ch.channel_removed = 0 ) as `channels` " .
- "FROM account as ac where true $serviceclass $order limit %d offset %d ",
- intval(ACCOUNT_BLOCKED),
- db_concat('ch.channel_address', ' '),
- intval(App::$pager['itemspage']),
- intval(App::$pager['start'])
- );
-
-// function _setup_users($e){
-// $accounts = Array(
-// t('Normal Account'),
-// t('Soapbox Account'),
-// t('Community/Celebrity Account'),
-// t('Automatic Friend Account')
-// );
-
-// $e['page_flags'] = $accounts[$e['page-flags']];
-// $e['register_date'] = relative_date($e['register_date']);
-// $e['login_date'] = relative_date($e['login_date']);
-// $e['lastitem_date'] = relative_date($e['lastitem_date']);
-// return $e;
-// }
-// $users = array_map("_setup_users", $users);
-
- $t = get_markup_template('admin_users.tpl');
- $o = replace_macros($t, array(
- // strings //
- '$title' => t('Administration'),
- '$page' => t('Users'),
- '$submit' => t('Submit'),
- '$select_all' => t('select all'),
- '$h_pending' => t('User registrations waiting for confirm'),
- '$th_pending' => array( t('Request date'), t('Email') ),
- '$no_pending' => t('No registrations.'),
- '$approve' => t('Approve'),
- '$deny' => t('Deny'),
- '$delete' => t('Delete'),
- '$block' => t('Block'),
- '$unblock' => t('Unblock'),
-
- '$h_users' => t('Users'),
- '$th_users' => array( t('ID'), t('Email'), t('All Channels'), t('Register date'), t('Last login'), t('Expires'), t('Service Class')),
-
- '$confirm_delete_multi' => t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?'),
- '$confirm_delete' => t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?'),
-
- '$form_security_token' => get_form_security_token("admin_users"),
-
- // values //
- '$baseurl' => z_root(),
-
- '$pending' => $pending,
- '$users' => $users,
- ));
- $o .= paginate($a);
-
- return $o;
-}
-
-
-/**
- * @brief Channels admin page.
- *
- * @param App &$a
- */
-function admin_page_channels_post(&$a) {
- $channels = ( x($_POST, 'channel') ? $_POST['channel'] : Array() );
-
- check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels');
-
- $xor = db_getfunc('^');
-
- if (x($_POST,'page_channels_block')){
- foreach($channels as $uid){
- q("UPDATE channel SET channel_pageflags = ( channel_pageflags $xor %d ) where channel_id = %d",
- intval(PAGE_CENSORED),
- intval( $uid )
- );
- proc_run('php','include/directory.php',$uid,'nopush');
- }
- notice( sprintf( tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)) );
- }
- if (x($_POST,'page_channels_code')){
- foreach($channels as $uid){
- q("UPDATE channel SET channel_pageflags = ( channel_pageflags $xor %d ) where channel_id = %d",
- intval(PAGE_ALLOWCODE),
- intval( $uid )
- );
- }
- notice( sprintf( tt("%s channel code allowed/disallowed", "%s channels code allowed/disallowed", count($channels)), count($channels)) );
- }
- if (x($_POST,'page_channels_delete')){
- require_once("include/Contact.php");
- foreach($channels as $uid){
- channel_remove($uid,true);
- }
- notice( sprintf( tt("%s channel deleted", "%s channels deleted", count($channels)), count($channels)) );
- }
-
- goaway(z_root() . '/admin/channels' );
-}
-
-/**
- * @brief
- *
- * @param App &$a
- * @return string
- */
-function admin_page_channels(&$a){
- if (argc() > 2) {
- $uid = argv(3);
- $channel = q("SELECT * FROM channel WHERE channel_id = %d",
- intval($uid)
- );
-
- if (! $channel) {
- notice( t('Channel not found') . EOL);
- goaway(z_root() . '/admin/channels' );
- }
-
- switch(argv(2)) {
- case "delete":{
- check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
- // delete channel
- require_once("include/Contact.php");
- channel_remove($uid,true);
-
- notice( sprintf(t("Channel '%s' deleted"), $channel[0]['channel_name']) . EOL);
- }; break;
-
- case "block":{
- check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
- $pflags = $channel[0]['channel_pageflags'] ^ PAGE_CENSORED;
- q("UPDATE channel SET channel_pageflags = %d where channel_id = %d",
- intval($pflags),
- intval( $uid )
- );
- proc_run('php','include/directory.php',$uid,'nopush');
-
- notice( sprintf( (($pflags & PAGE_CENSORED) ? t("Channel '%s' censored"): t("Channel '%s' uncensored")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL);
- }; break;
-
- case "code":{
- check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
- $pflags = $channel[0]['channel_pageflags'] ^ PAGE_ALLOWCODE;
- q("UPDATE channel SET channel_pageflags = %d where channel_id = %d",
- intval($pflags),
- intval( $uid )
- );
-
- notice( sprintf( (($pflags & PAGE_ALLOWCODE) ? t("Channel '%s' code allowed"): t("Channel '%s' code disallowed")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL);
- }; break;
-
- default:
- break;
- }
- goaway(z_root() . '/admin/channels' );
- }
-
- /* get channels */
-
- $total = q("SELECT count(*) as total FROM channel where channel_removed = 0 and channel_system = 0");
- if($total) {
- App::set_pager_total($total[0]['total']);
- App::set_pager_itemspage(100);
- }
-
- $order = " order by channel_name asc ";
-
- $channels = q("SELECT * from channel where channel_removed = 0 and channel_system = 0 $order limit %d offset %d ",
- intval(App::$pager['itemspage']),
- intval(App::$pager['start'])
- );
-
- if($channels) {
- for($x = 0; $x < count($channels); $x ++) {
- if($channels[$x]['channel_pageflags'] & PAGE_CENSORED)
- $channels[$x]['blocked'] = true;
- else
- $channels[$x]['blocked'] = false;
-
- if($channels[$x]['channel_pageflags'] & PAGE_ALLOWCODE)
- $channels[$x]['allowcode'] = true;
- else
- $channels[$x]['allowcode'] = false;
- }
- }
-
- $t = get_markup_template("admin_channels.tpl");
- $o = replace_macros($t, array(
- // strings //
- '$title' => t('Administration'),
- '$page' => t('Channels'),
- '$submit' => t('Submit'),
- '$select_all' => t('select all'),
- '$delete' => t('Delete'),
- '$block' => t('Censor'),
- '$unblock' => t('Uncensor'),
- '$code' => t('Allow Code'),
- '$uncode' => t('Disallow Code'),
- '$h_channels' => t('Channel'),
- '$th_channels' => array( t('UID'), t('Name'), t('Address')),
-
- '$confirm_delete_multi' => t('Selected channels will be deleted!\n\nEverything that was posted in these channels on this site will be permanently deleted!\n\nAre you sure?'),
- '$confirm_delete' => t('The channel {0} will be deleted!\n\nEverything that was posted in this channel on this site will be permanently deleted!\n\nAre you sure?'),
-
- '$form_security_token' => get_form_security_token("admin_channels"),
-
- // values //
- '$baseurl' => z_root(),
- '$channels' => $channels,
- ));
- $o .= paginate($a);
-
- return $o;
-}
-
-
-/**
- * Plugins admin page
- *
- * @param App $a
- * @return string
- */
-function admin_page_plugins(&$a){
-
- /*
- * Single plugin
- */
- if (App::$argc == 3){
- $plugin = App::$argv[2];
- if (!is_file("addon/$plugin/$plugin.php")){
- notice( t("Item not found.") );
- return '';
- }
-
- $enabled = in_array($plugin,App::$plugins);
- $info = get_plugin_info($plugin);
- $x = check_plugin_versions($info);
-
- // disable plugins which are installed but incompatible versions
-
- if($enabled && ! $x) {
- $enabled = false;
- $idz = array_search($plugin, App::$plugins);
- if ($idz !== false) {
- unset(App::$plugins[$idz]);
- uninstall_plugin($plugin);
- set_config("system","addon", implode(", ",App::$plugins));
- }
- }
- $info['disabled'] = 1-intval($x);
-
- if (x($_GET,"a") && $_GET['a']=="t"){
- check_form_security_token_redirectOnErr('/admin/plugins', 'admin_plugins', 't');
-
- // Toggle plugin status
- $idx = array_search($plugin, App::$plugins);
- if ($idx !== false){
- unset(App::$plugins[$idx]);
- uninstall_plugin($plugin);
- info( sprintf( t("Plugin %s disabled."), $plugin ) );
- } else {
- App::$plugins[] = $plugin;
- install_plugin($plugin);
- info( sprintf( t("Plugin %s enabled."), $plugin ) );
- }
- set_config("system","addon", implode(", ",App::$plugins));
- goaway(z_root() . '/admin/plugins' );
- }
- // display plugin details
- require_once('library/markdown.php');
-
- if (in_array($plugin, App::$plugins)){
- $status = 'on';
- $action = t('Disable');
- } else {
- $status = 'off';
- $action = t('Enable');
- }
-
- $readme = null;
- if (is_file("addon/$plugin/README.md")){
- $readme = file_get_contents("addon/$plugin/README.md");
- $readme = Markdown($readme);
- } else if (is_file("addon/$plugin/README")){
- $readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>";
- }
-
- $admin_form = '';
-
- $r = q("select * from addon where plugin_admin = 1 and name = '%s' limit 1",
- dbesc($plugin)
- );
-
- if($r) {
- @require_once("addon/$plugin/$plugin.php");
- if(function_exists($plugin.'_plugin_admin')) {
- $func = $plugin.'_plugin_admin';
- $func($a, $admin_form);
- }
- }
-
-
- $t = get_markup_template('admin_plugins_details.tpl');
- return replace_macros($t, array(
- '$title' => t('Administration'),
- '$page' => t('Plugins'),
- '$toggle' => t('Toggle'),
- '$settings' => t('Settings'),
- '$baseurl' => z_root(),
-
- '$plugin' => $plugin,
- '$status' => $status,
- '$action' => $action,
- '$info' => $info,
- '$str_author' => t('Author: '),
- '$str_maintainer' => t('Maintainer: '),
- '$str_minversion' => t('Minimum project version: '),
- '$str_maxversion' => t('Maximum project version: '),
- '$str_minphpversion' => t('Minimum PHP version: '),
- '$str_requires' => t('Requires: '),
- '$disabled' => t('Disabled - version incompatibility'),
-
- '$admin_form' => $admin_form,
- '$function' => 'plugins',
- '$screenshot' => '',
- '$readme' => $readme,
-
- '$form_security_token' => get_form_security_token('admin_plugins'),
- ));
- }
-
-
- /*
- * List plugins
- */
- $plugins = array();
- $files = glob('addon/*/');
- if($files) {
- foreach($files as $file) {
- if (is_dir($file)){
- list($tmp, $id) = array_map('trim', explode('/', $file));
- $info = get_plugin_info($id);
- $enabled = in_array($id,App::$plugins);
- $x = check_plugin_versions($info);
-
- // disable plugins which are installed but incompatible versions
-
- if($enabled && ! $x) {
- $enabled = false;
- $idz = array_search($id, App::$plugins);
- if ($idz !== false) {
- unset(App::$plugins[$idz]);
- uninstall_plugin($id);
- set_config("system","addon", implode(", ",App::$plugins));
- }
- }
- $info['disabled'] = 1-intval($x);
-
- $plugins[] = array( $id, (($enabled)?"on":"off") , $info);
- }
- }
- }
-
- $t = get_markup_template('admin_plugins.tpl');
- return replace_macros($t, array(
- '$title' => t('Administration'),
- '$page' => t('Plugins'),
- '$submit' => t('Submit'),
- '$baseurl' => z_root(),
- '$function' => 'plugins',
- '$plugins' => $plugins,
- '$disabled' => t('Disabled - version incompatibility'),
- '$form_security_token' => get_form_security_token('admin_plugins'),
- ));
-}
-
-/**
- * @param array $themes
- * @param string $th
- * @param int $result
- */
-function toggle_theme(&$themes, $th, &$result) {
- for($x = 0; $x < count($themes); $x ++) {
- if($themes[$x]['name'] === $th) {
- if($themes[$x]['allowed']) {
- $themes[$x]['allowed'] = 0;
- $result = 0;
- }
- else {
- $themes[$x]['allowed'] = 1;
- $result = 1;
- }
- }
- }
-}
-
-/**
- * @param array $themes
- * @param string $th
- * @return int
- */
-function theme_status($themes, $th) {
- for($x = 0; $x < count($themes); $x ++) {
- if($themes[$x]['name'] === $th) {
- if($themes[$x]['allowed']) {
- return 1;
- }
- else {
- return 0;
- }
- }
- }
- return 0;
-}
-
-
-/**
- * @param array $themes
- * @return string
- */
-function rebuild_theme_table($themes) {
- $o = '';
- if(count($themes)) {
- foreach($themes as $th) {
- if($th['allowed']) {
- if(strlen($o))
- $o .= ',';
- $o .= $th['name'];
- }
- }
- }
- return $o;
-}
-
-
-/**
- * @brief Themes admin page.
- *
- * @param App &$a
- * @return string
- */
-function admin_page_themes(&$a){
-
- $allowed_themes_str = get_config('system', 'allowed_themes');
- $allowed_themes_raw = explode(',', $allowed_themes_str);
- $allowed_themes = array();
- if(count($allowed_themes_raw))
- foreach($allowed_themes_raw as $x)
- if(strlen(trim($x)))
- $allowed_themes[] = trim($x);
-
- $themes = array();
- $files = glob('view/theme/*');
- if($files) {
- foreach($files as $file) {
- $f = basename($file);
- $is_experimental = intval(file_exists($file . '/.experimental'));
- $is_supported = 1-(intval(file_exists($file . '/.unsupported'))); // Is not used yet
- $is_allowed = intval(in_array($f,$allowed_themes));
- $themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed);
- }
- }
-
- if(! count($themes)) {
- notice( t('No themes found.'));
- return '';
- }
-
- /*
- * Single theme
- */
-
- if (App::$argc == 3){
- $theme = App::$argv[2];
- if(! is_dir("view/theme/$theme")){
- notice( t("Item not found.") );
- return '';
- }
-
- if (x($_GET,"a") && $_GET['a']=="t"){
- check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't');
-
- // Toggle theme status
-
- toggle_theme($themes, $theme, $result);
- $s = rebuild_theme_table($themes);
- if($result)
- info( sprintf('Theme %s enabled.', $theme));
- else
- info( sprintf('Theme %s disabled.', $theme));
-
- set_config('system', 'allowed_themes', $s);
- goaway(z_root() . '/admin/themes' );
- }
-
- // display theme details
- require_once('library/markdown.php');
-
- if (theme_status($themes,$theme)) {
- $status="on"; $action= t("Disable");
- } else {
- $status="off"; $action= t("Enable");
- }
-
- $readme=Null;
- if (is_file("view/theme/$theme/README.md")){
- $readme = file_get_contents("view/theme/$theme/README.md");
- $readme = Markdown($readme);
- } else if (is_file("view/theme/$theme/README")){
- $readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>";
- }
-
- $admin_form = '';
- if (is_file("view/theme/$theme/php/config.php")){
- require_once("view/theme/$theme/php/config.php");
- if(function_exists("theme_admin")){
- $admin_form = theme_admin($a);
- }
- }
-
- $screenshot = array( get_theme_screenshot($theme), t('Screenshot'));
- if(! stristr($screenshot[0],$theme))
- $screenshot = null;
-
- $t = get_markup_template('admin_plugins_details.tpl');
- return replace_macros($t, array(
- '$title' => t('Administration'),
- '$page' => t('Themes'),
- '$toggle' => t('Toggle'),
- '$settings' => t('Settings'),
- '$baseurl' => z_root(),
-
- '$plugin' => $theme,
- '$status' => $status,
- '$action' => $action,
- '$info' => get_theme_info($theme),
- '$function' => 'themes',
- '$admin_form' => $admin_form,
- '$str_author' => t('Author: '),
- '$str_maintainer' => t('Maintainer: '),
- '$screenshot' => $screenshot,
- '$readme' => $readme,
-
- '$form_security_token' => get_form_security_token('admin_themes'),
- ));
- }
-
- /*
- * List themes
- */
-
- $xthemes = array();
- if($themes) {
- foreach($themes as $th) {
- $xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name']));
- }
- }
-
- $t = get_markup_template('admin_plugins.tpl');
- return replace_macros($t, array(
- '$title' => t('Administration'),
- '$page' => t('Themes'),
- '$submit' => t('Submit'),
- '$baseurl' => z_root(),
- '$function' => 'themes',
- '$plugins' => $xthemes,
- '$experimental' => t('[Experimental]'),
- '$unsupported' => t('[Unsupported]'),
- '$form_security_token' => get_form_security_token('admin_themes'),
- ));
-}
-
-
-/**
- * @brief POST handler for logs admin page.
- *
- * @param App &$a
- */
-function admin_page_logs_post(&$a) {
- if (x($_POST, 'page_logs')) {
- check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs');
-
- $logfile = ((x($_POST,'logfile')) ? notags(trim($_POST['logfile'])) : '');
- $debugging = ((x($_POST,'debugging')) ? true : false);
- $loglevel = ((x($_POST,'loglevel')) ? intval(trim($_POST['loglevel'])) : 0);
-
- set_config('system','logfile', $logfile);
- set_config('system','debugging', $debugging);
- set_config('system','loglevel', $loglevel);
- }
-
- info( t('Log settings updated.') );
- goaway(z_root() . '/admin/logs' );
-}
-
-/**
- * @brief Logs admin page.
- *
- * @param App $a
- * @return string
- */
-function admin_page_logs(&$a){
-
- $log_choices = Array(
- LOGGER_NORMAL => 'Normal',
- LOGGER_TRACE => 'Trace',
- LOGGER_DEBUG => 'Debug',
- LOGGER_DATA => 'Data',
- LOGGER_ALL => 'All'
- );
-
- $t = get_markup_template('admin_logs.tpl');
-
- $f = get_config('system', 'logfile');
-
- $data = '';
-
- if(!file_exists($f)) {
- $data = t("Error trying to open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f exist and is
-readable.");
- }
- else {
- $fp = fopen($f, 'r');
- if(!$fp) {
- $data = t("Couldn't open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f is readable.");
- }
- else {
- $fstat = fstat($fp);
- $size = $fstat['size'];
- if($size != 0)
- {
- if($size > 5000000 || $size < 0)
- $size = 5000000;
- $seek = fseek($fp,0-$size,SEEK_END);
- if($seek === 0) {
- $data = escape_tags(fread($fp,$size));
- while(! feof($fp))
- $data .= escape_tags(fread($fp,4096));
- }
- }
- fclose($fp);
- }
- }
-
- return replace_macros($t, array(
- '$title' => t('Administration'),
- '$page' => t('Logs'),
- '$submit' => t('Submit'),
- '$clear' => t('Clear'),
- '$data' => $data,
- '$baseurl' => z_root(),
- '$logname' => get_config('system','logfile'),
-
- // name, label, value, help string, extra data...
- '$debugging' => array('debugging', t("Debugging"),get_config('system','debugging'), ""),
- '$logfile' => array('logfile', t("Log file"), get_config('system','logfile'), t("Must be writable by web server. Relative to your Red top-level directory.")),
- '$loglevel' => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices),
-
- '$form_security_token' => get_form_security_token('admin_logs'),
- ));
-}
-
-function admin_page_profs_post(&$a) {
-
- if(array_key_exists('basic',$_REQUEST)) {
- $arr = explode(',',$_REQUEST['basic']);
- for($x = 0; $x < count($arr); $x ++)
- if(trim($arr[$x]))
- $arr[$x] = trim($arr[$x]);
- set_config('system','profile_fields_basic',$arr);
-
- if(array_key_exists('advanced',$_REQUEST)) {
- $arr = explode(',',$_REQUEST['advanced']);
- for($x = 0; $x < count($arr); $x ++)
- if(trim($arr[$x]))
- $arr[$x] = trim($arr[$x]);
- set_config('system','profile_fields_advanced',$arr);
- }
- goaway(z_root() . '/admin/profs');
- }
-
-
- if(array_key_exists('field_name',$_REQUEST)) {
- if($_REQUEST['id']) {
- $r = q("update profdef set field_name = '%s', field_type = '%s', field_desc = '%s' field_help = '%s', field_inputs = '%s' where id = %d",
- dbesc($_REQUEST['field_name']),
- dbesc($_REQUEST['field_type']),
- dbesc($_REQUEST['field_desc']),
- dbesc($_REQUEST['field_help']),
- dbesc($_REQUEST['field_inputs']),
- intval($_REQUEST['id'])
- );
- }
- else {
- $r = q("insert into profdef ( field_name, field_type, field_desc, field_help, field_inputs ) values ( '%s' , '%s', '%s', '%s', '%s' )",
- dbesc($_REQUEST['field_name']),
- dbesc($_REQUEST['field_type']),
- dbesc($_REQUEST['field_desc']),
- dbesc($_REQUEST['field_help']),
- dbesc($_REQUEST['field_inputs'])
- );
- }
- }
-
-
- // add to chosen array basic or advanced
-
- goaway(z_root() . '/admin/profs');
-}
-
-function admin_page_profs(&$a) {
-
- if((argc() > 3) && argv(2) == 'drop' && intval(argv(3))) {
- $r = q("delete from profdef where id = %d",
- intval(argv(3))
- );
- // remove from allowed fields
-
- goaway(z_root() . '/admin/profs');
- }
-
- if((argc() > 2) && argv(2) === 'new') {
- return replace_macros(get_markup_template('profdef_edit.tpl'),array(
- '$header' => t('New Profile Field'),
- '$field_name' => array('field_name',t('Field nickname'),$_REQUEST['field_name'],t('System name of field')),
- '$field_type' => array('field_type',t('Input type'),(($_REQUEST['field_type']) ? $_REQUEST['field_type'] : 'text'),''),
- '$field_desc' => array('field_desc',t('Field Name'),$_REQUEST['field_desc'],t('Label on profile pages')),
- '$field_help' => array('field_help',t('Help text'),$_REQUEST['field_help'],t('Additional info (optional)')),
- '$submit' => t('Save')
- ));
- }
-
- if((argc() > 2) && intval(argv(2))) {
- $r = q("select * from profdef where id = %d limit 1",
- intval(argv(2))
- );
- if(! $r) {
- notice( t('Field definition not found') . EOL);
- goaway(z_root() . '/admin/profs');
- }
-
- return replace_macros(get_markup_template('profdef_edit.tpl'),array(
- '$id' => intval($r[0]['id']),
- '$header' => t('Edit Profile Field'),
- '$field_name' => array('field_name',t('Field nickname'),$r[0]['field_name'],t('System name of field')),
- '$field_type' => array('field_type',t('Input type'),$r[0]['field_type'],''),
- '$field_desc' => array('field_desc',t('Field Name'),$r[0]['field_desc'],t('Label on profile pages')),
- '$field_help' => array('field_help',t('Help text'),$r[0]['field_help'],t('Additional info (optional)')),
- '$submit' => t('Save')
- ));
- }
-
- $basic = '';
- $barr = array();
- $fields = get_profile_fields_basic();
- if(! $fields)
- $fields = get_profile_fields_basic(1);
- if($fields) {
- foreach($fields as $k => $v) {
- if($basic)
- $basic .= ', ';
- $basic .= trim($k);
- $barr[] = trim($k);
- }
- }
-
- $advanced = '';
- $fields = get_profile_fields_advanced();
- if(! $fields)
- $fields = get_profile_fields_advanced(1);
- if($fields) {
- foreach($fields as $k => $v) {
- if(in_array(trim($k),$barr))
- continue;
- if($advanced)
- $advanced .= ', ';
- $advanced .= trim($k);
- }
- }
-
- $all = '';
- $fields = get_profile_fields_advanced(1);
- if($fields) {
- foreach($fields as $k => $v) {
- if($all)
- $all .= ', ';
- $all .= trim($k);
- }
- }
-
- $r = q("select * from profdef where true");
- if($r) {
- foreach($r as $rr) {
- if($all)
- $all .= ', ';
- $all .= $rr['field_name'];
- }
- }
-
-
- $o = replace_macros(get_markup_template('admin_profiles.tpl'),array(
- '$title' => t('Profile Fields'),
- '$basic' => array('basic',t('Basic Profile Fields'),$basic,''),
- '$advanced' => array('advanced',t('Advanced Profile Fields'),$advanced,t('(In addition to basic fields)')),
- '$all' => $all,
- '$all_desc' => t('All available fields'),
- '$cust_field_desc' => t('Custom Fields'),
- '$cust_fields' => $r,
- '$edit' => t('Edit'),
- '$drop' => t('Delete'),
- '$new' => t('Create Custom Field'),
- '$submit' => t('Submit')
- ));
-
- return $o;
-
-
-}
diff --git a/mod/api.php b/mod/api.php
deleted file mode 100644
index aa95b81dd..000000000
--- a/mod/api.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-
-require_once('include/api.php');
-
-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];
-}
-
-function api_post(&$a) {
-
- 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 api_content(&$a) {
- 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 = 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 = 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();
-}
-
-
-
diff --git a/mod/appman.php b/mod/appman.php
deleted file mode 100644
index d8d030465..000000000
--- a/mod/appman.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php /** @file */
-
-require_once('include/apps.php');
-
-function appman_post(&$a) {
-
- 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']),
- 'sig' => escape_tags($_REQUEST['sig'])
- );
-
- $_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 appman_content(&$a) {
-
- 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];
- $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')),
- '$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'] : ''), ''),
- '$embed' => $embed,
- '$submit' => t('Submit')
- ));
-
-}
diff --git a/mod/apps.php b/mod/apps.php
deleted file mode 100644
index 3539b2bc0..000000000
--- a/mod/apps.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-require_once('include/apps.php');
-
-function apps_content(&$a) {
-
- if(argc() == 2 && argv(1) == 'edit')
- $mode = 'edit';
- else
- $mode = 'list';
-
- $_SESSION['return_url'] = App::$cmd;
-
- $apps = array();
-
- $syslist = get_system_apps();
-
- if(local_channel()) {
- $list = app_list(local_channel());
- if($list) {
- foreach($list as $x) {
- $syslist[] = app_encode($x);
- }
- }
- }
- 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'),
- '$title' => t('Apps'),
- '$apps' => $apps,
- ));
-
-}
diff --git a/mod/attach.php b/mod/attach.php
deleted file mode 100644
index 306e39519..000000000
--- a/mod/attach.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-require_once('include/security.php');
-require_once('include/attach.php');
-
-function attach_init(&$a) {
-
- 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();
-
-}
diff --git a/mod/authtest.php b/mod/authtest.php
deleted file mode 100644
index 6ef6c22ad..000000000
--- a/mod/authtest.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-require_once('include/zot.php');
-require_once('mod/magic.php');
-
-function authtest_content(&$a) {
-
-
- $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;
- $x = magic_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);
-}
diff --git a/mod/block.php b/mod/block.php
deleted file mode 100644
index 301993d03..000000000
--- a/mod/block.php
+++ /dev/null
@@ -1,86 +0,0 @@
-<?php
-
-require_once('include/items.php');
-require_once('include/conversation.php');
-require_once('include/page_widgets.php');
-
-function block_init(&$a) {
-
- $which = argv(1);
- $profile = 0;
- profile_load($a,$which,$profile);
-
- if(App::$profile['profile_uid'])
- head_set_icon(App::$profile['thumb']);
-
-}
-
-
-function block_content(&$a) {
-
- 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;
-
-}
diff --git a/mod/blocks.php b/mod/blocks.php
deleted file mode 100644
index 3c9274991..000000000
--- a/mod/blocks.php
+++ /dev/null
@@ -1,166 +0,0 @@
-<?php
-
-require_once('include/identity.php');
-require_once('include/conversation.php');
-require_once('include/acl_selectors.php');
-
-function blocks_init(&$a) {
-
- 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 blocks_content(&$a) {
-
- 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'));
-
- if(! $mimetype) {
- $mimetype = 'choose';
- }
-
- $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,
- '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;
-}
diff --git a/mod/bookmarks.php b/mod/bookmarks.php
deleted file mode 100644
index 5c48ce5a9..000000000
--- a/mod/bookmarks.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-function bookmarks_init(&$a) {
- 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 bookmarks_content(&$a) {
- 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;
-
-}
-
diff --git a/mod/branchtopic.php b/mod/branchtopic.php
deleted file mode 100644
index 3702e6d53..000000000
--- a/mod/branchtopic.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-function branchtopic_init(&$a) {
-
- 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;
-}
diff --git a/mod/cal.php b/mod/cal.php
deleted file mode 100755
index 56d65d3f2..000000000
--- a/mod/cal.php
+++ /dev/null
@@ -1,351 +0,0 @@
-<?php
-
-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');
-
-
-function cal_init(&$a) {
- 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 ispublic = '" . t('everybody') . "'; var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ;
-
- }
-
- return;
-}
-
-
-
-function cal_content(&$a) {
-
- 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;
- }
-
-}
diff --git a/mod/chanview.php b/mod/chanview.php
deleted file mode 100644
index 705fb5a7d..000000000
--- a/mod/chanview.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-
-require_once('include/Contact.php');
-require_once('include/zot.php');
-
-function chanview_content(&$a) {
-
- $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;
-
-}
diff --git a/mod/chat.php b/mod/chat.php
deleted file mode 100644
index 375d069be..000000000
--- a/mod/chat.php
+++ /dev/null
@@ -1,255 +0,0 @@
-<?php /** @file */
-
-require_once('include/chat.php');
-require_once('include/bookmarks.php');
-
-function chat_init(&$a) {
-
- $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 chat_post(&$a) {
-
- 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 chat_content(&$a) {
-
- 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;
-
-}
diff --git a/mod/chatsvc.php b/mod/chatsvc.php
deleted file mode 100644
index 4fa38e819..000000000
--- a/mod/chatsvc.php
+++ /dev/null
@@ -1,162 +0,0 @@
-<?php /** @file */
-
-require_once('include/security.php');
-
-function chatsvc_init(&$a) {
-
-//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 chatsvc_post(&$a) {
-
- $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 chatsvc_content(&$a) {
-
- $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);
-
-}
-
diff --git a/mod/cloud.php b/mod/cloud.php
deleted file mode 100644
index eed941ff7..000000000
--- a/mod/cloud.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-/**
- * @file mod/cloud.php
- * @brief Initialize Hubzilla's cloud (SabreDAV).
- *
- * Module for accessing the DAV storage area.
- */
-
-use Sabre\DAV;
-use Zotlabs\Storage;
-
-// composer autoloader for SabreDAV
-require_once('vendor/autoload.php');
-
-/**
- * @brief Fires up the SabreDAV server.
- *
- * @param App &$a
- */
-
-function cloud_init(&$a) {
- 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 DAV\Server($rootDirectory);
- // prevent overwriting changes each other with a lock backend
- $lockBackend = new DAV\Locks\Backend\File('store/[data]/locks');
- $lockPlugin = new DAV\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.');
- }
- }
- }
-
-// require_once('Zotlabs/Storage/Browser.php');
- // 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();
-}
diff --git a/mod/common.php b/mod/common.php
deleted file mode 100644
index 3390bd997..000000000
--- a/mod/common.php
+++ /dev/null
@@ -1,67 +0,0 @@
-<?php
-
-require_once('include/socgraph.php');
-
-function common_init(&$a) {
-
- 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 common_content(&$a) {
-
- $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;
-}
diff --git a/mod/connect.php b/mod/connect.php
deleted file mode 100644
index 84c67e4d2..000000000
--- a/mod/connect.php
+++ /dev/null
@@ -1,125 +0,0 @@
-<?php /** @file */
-
-
-require_once('include/Contact.php');
-require_once('include/contact_widgets.php');
-require_once('include/items.php');
-
-
-function connect_init(&$a) {
- 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 connect_post(&$a) {
-
- 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 connect_content(&$a) {
-
- $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;
-} \ No newline at end of file
diff --git a/mod/connections.php b/mod/connections.php
deleted file mode 100644
index 992d485bd..000000000
--- a/mod/connections.php
+++ /dev/null
@@ -1,318 +0,0 @@
-<?php
-
-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');
-
-function connections_init(&$a) {
-
- if(! local_channel())
- return;
-
- $channel = App::get_channel();
- if($channel)
- head_set_icon($channel['xchan_photo_s']);
-
-}
-
-function connections_content(&$a) {
-
- $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;
-}
diff --git a/mod/connedit.php b/mod/connedit.php
deleted file mode 100644
index f57fdefc6..000000000
--- a/mod/connedit.php
+++ /dev/null
@@ -1,756 +0,0 @@
-<?php
-
-/* @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');
-
-/* @brief Initialize the connection-editor
- *
- *
- */
-
-function connedit_init(&$a) {
-
- 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 connedit_post(&$a) {
-
- 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');
- require_once('mod/profile_photo.php');
- 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));
-
- 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 connedit_content(&$a) {
-
- $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)) {
- 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)) {
- 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)) {
- 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)) {
- 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)) {
- 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;
-
- $buttons = 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.'),
- '$buttons' => (($self) ? '' : $buttons),
- '$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'];
-
- }
-
-
-}
diff --git a/mod/contactgroup.php b/mod/contactgroup.php
deleted file mode 100644
index 61ca37054..000000000
--- a/mod/contactgroup.php
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-
-require_once('include/group.php');
-
-function contactgroup_content(&$a) {
-
- 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();
-} \ No newline at end of file
diff --git a/mod/cover_photo.php b/mod/cover_photo.php
deleted file mode 100644
index c99fdf7de..000000000
--- a/mod/cover_photo.php
+++ /dev/null
@@ -1,417 +0,0 @@
-<?php
-
-/*
- @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
- *
- */
-
-function cover_photo_init(&$a) {
-
- 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 cover_photo_post(&$a) {
-
- 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();
- 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 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 cover_photo_content(&$a) {
-
- 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;
-}
-
diff --git a/mod/dav.php b/mod/dav.php
deleted file mode 100644
index e2a857dca..000000000
--- a/mod/dav.php
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-/**
- * @file mod/dav.php
- * @brief Initialize Hubzilla's cloud (SabreDAV).
- *
- * Module for accessing the DAV storage area from a DAV client.
- */
-
-use Sabre\DAV;
-use Zotlabs\Storage;
-
-// composer autoloader for SabreDAV
-require_once('vendor/autoload.php');
-
-// 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;
- }
-}
-
-/**
- * @brief Fires up the SabreDAV server.
- *
- * @param App &$a
- */
-function dav_init(&$a) {
-
- 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 DAV\Server($rootDirectory);
- // prevent overwriting changes each other with a lock backend
- $lockBackend = new DAV\Locks\Backend\File('store/[data]/locks');
- $lockPlugin = new DAV\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();
-}
diff --git a/mod/directory.php b/mod/directory.php
deleted file mode 100644
index 79c03777e..000000000
--- a/mod/directory.php
+++ /dev/null
@@ -1,419 +0,0 @@
-<?php
-
-require_once('include/socgraph.php');
-require_once('include/dir_fns.php');
-require_once('include/widgets.php');
-require_once('include/bbcode.php');
-
-function directory_init(&$a) {
- 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 directory_content(&$a) {
-
- 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;
-}
-
diff --git a/mod/dirsearch.php b/mod/dirsearch.php
deleted file mode 100644
index 1273c5ccd..000000000
--- a/mod/dirsearch.php
+++ /dev/null
@@ -1,456 +0,0 @@
-<?php
-
-require_once('include/dir_fns.php');
-
-
-function dirsearch_init(&$a) {
- App::set_pager_itemspage(60);
-
-}
-
-function dirsearch_content(&$a) {
-
- $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 = 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 = dir_parse_query($_REQUEST['query']);
- if($advanced) {
- foreach($advanced as $adv) {
- if(in_array($adv['field'],$tables)) {
- if($adv['field'] === 'name')
- $sql_extra .= dir_query_build($adv['logic'],'xchan_name',$adv['value']);
- elseif($adv['field'] === 'address')
- $sql_extra .= dir_query_build($adv['logic'],'xchan_addr',$adv['value']);
- else
- $sql_extra .= 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 .= dir_query_build($joiner,'xchan_name',$name);
- if($address)
- $sql_extra .= dir_query_build($joiner,'xchan_addr',$address);
- if($city)
- $sql_extra .= dir_query_build($joiner,'xprof_locale',$city);
- if($region)
- $sql_extra .= dir_query_build($joiner,'xprof_region',$region);
- if($post)
- $sql_extra .= dir_query_build($joiner,'xprof_postcode',$post);
- if($country)
- $sql_extra .= dir_query_build($joiner,'xprof_country',$country);
- if($gender)
- $sql_extra .= dir_query_build($joiner,'xprof_gender',$gender);
- if($marital)
- $sql_extra .= dir_query_build($joiner,'xprof_marital',$marital);
- if($sexual)
- $sql_extra .= dir_query_build($joiner,'xprof_sexual',$sexual);
- if($keywords)
- $sql_extra .= 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;
-}
diff --git a/mod/display.php b/mod/display.php
deleted file mode 100644
index 2844a1205..000000000
--- a/mod/display.php
+++ /dev/null
@@ -1,340 +0,0 @@
-<?php
-
-
-function display_content(&$a, $update = 0, $load = false) {
-
-// logger("mod-display: update = $update load = $load");
-
-
- $checkjs = new Zotlabs\Web\CheckJS();
-
-
- 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 );
- }
-
- }
-*/
-}
-
diff --git a/mod/dreport.php b/mod/dreport.php
deleted file mode 100644
index 4edec2e2b..000000000
--- a/mod/dreport.php
+++ /dev/null
@@ -1,139 +0,0 @@
-<?php
-
-function dreport_content(&$a) {
-
- 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,'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;
-
-
-
-}
-
-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));
-}
diff --git a/mod/editblock.php b/mod/editblock.php
deleted file mode 100644
index 214c495dd..000000000
--- a/mod/editblock.php
+++ /dev/null
@@ -1,192 +0,0 @@
-<?php
-
-require_once('include/identity.php');
-require_once('include/acl_selectors.php');
-
-function editblock_init(&$a) {
-
- 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 editblock_content(&$a) {
-
- 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;
- }
-
- $plaintext = true;
-
- $mimeselect = '';
- $mimetype = $itm[0]['mimetype'];
-
- if($mimetype != 'text/bbcode')
- $plaintext = true;
-
- if(get_config('system','page_mimetype'))
- $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />';
- else
- $mimeselect = mimetype_select($itm[0]['uid'],$mimetype);
-
- App::$page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array(
- '$baseurl' => z_root(),
- '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
- '$pretext' => '',
- '$ispublic' => '&nbsp;', // t('Visible to <strong>everybody</strong>'),
- '$geotag' => '',
- '$nickname' => $channel['channel_address'],
- '$confirmdelete' => t('Delete block?'),
- '$bbco_autocomplete'=> (($mimetype == 'text/bbcode') ? 'bbcode' : 'comanche-block')
- ));
-
- $tpl = get_markup_template("jot.tpl");
-
- $jotplugins = '';
- $jotnets = '';
-
- call_hooks('jot_tool', $jotplugins);
- call_hooks('jot_networks', $jotnets);
-
- $rp = 'blocks/' . $channel['channel_address'];
-
- $editor = replace_macros($tpl,array(
- '$return_path' => $rp,
- '$action' => 'item',
- '$webpage' => ITEM_TYPE_BLOCK,
- '$share' => t('Edit'),
- '$bold' => t('Bold'),
- '$italic' => t('Italic'),
- '$underline' => t('Underline'),
- '$quote' => t('Quote'),
- '$code' => t('Code'),
- '$writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_storage'),
- '$upload' => t('Upload photo'),
- '$attach' => t('Attach file'),
- '$weblink' => t('Insert web link'),
- '$youtube' => t('Insert YouTube video'),
- '$video' => t('Insert Vorbis [.ogg] video'),
- '$audio' => t('Insert Vorbis [.ogg] audio'),
- '$setloc' => t('Set your location'),
- '$noloc' => t('Clear browser location'),
- '$wait' => t('Please wait'),
- '$permset' => t('Permission settings'),
- '$ptyp' => $itm[0]['type'],
- '$mimeselect' => $mimeselect,
- '$content' => undo_post_tagging($itm[0]['body']),
- '$post_id' => $post_id,
- '$baseurl' => z_root(),
- '$defloc' => $channel['channel_location'],
- '$visitor' => false,
- '$public' => t('Public post'),
- '$jotnets' => $jotnets,
- '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
- '$placeholdertitle' => t('Title (optional)'),
- '$pagetitle' => $block_title,
- '$category' => '',
- '$placeholdercategory' => t('Categories (optional, comma-separated list)'),
- '$emtitle' => t('Example: bob@example.com, mary@example.com'),
- '$lockstate' => $lockstate,
- '$acl' => '',
- '$bang' => '',
- '$profile_uid' => (intval($channel['channel_id'])),
- '$preview' => t('Preview'),
- '$jotplugins' => $jotplugins,
- '$sourceapp' => $itm[0]['app'],
- '$defexpire' => '',
- '$feature_expire' => false,
- '$expires' => t('Set expiration date'),
- '$bbcode' => (($mimetype == 'text/bbcode') ? true : false)
- ));
-
- $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;
-
-}
-
-
diff --git a/mod/editlayout.php b/mod/editlayout.php
deleted file mode 100644
index 0b58fe5fe..000000000
--- a/mod/editlayout.php
+++ /dev/null
@@ -1,189 +0,0 @@
-<?php
-
-require_once('include/identity.php');
-require_once('include/acl_selectors.php');
-
-function editlayout_init(&$a) {
-
- 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 editlayout_content(&$a) {
-
- 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'];
-
- $plaintext = true;
-
- App::$page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array(
- '$baseurl' => z_root(),
- '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
- '$pretext' => '',
- '$ispublic' => '&nbsp;', // t('Visible to <strong>everybody</strong>'),
- '$geotag' => $geotag,
- '$nickname' => $channel['channel_address'],
- '$confirmdelete' => t('Delete layout?'),
- '$bbco_autocomplete'=> 'comanche'
- ));
-
-
- $tpl = get_markup_template("jot.tpl");
-
- $jotplugins = '';
- $jotnets = '';
-
- call_hooks('jot_tool', $jotplugins);
- call_hooks('jot_networks', $jotnets);
-
-
- // FIXME A return path with $_SESSION doesn't always work for observer - it may WSoD
- // instead of loading a sensible page. So, send folk to the webpage list.
-
- $rp = 'layouts/' . $which;
-
- $editor = replace_macros($tpl,array(
- '$return_path' => $rp,
- '$action' => 'item',
- '$webpage' => ITEM_TYPE_PDL,
- '$share' => t('Edit'),
- '$bold' => t('Bold'),
- '$italic' => t('Italic'),
- '$underline' => t('Underline'),
- '$quote' => t('Quote'),
- '$code' => t('Code'),
- '$upload' => t('Upload photo'),
- '$attach' => t('Attach file'),
- '$weblink' => t('Insert web link'),
- '$youtube' => t('Insert YouTube video'),
- '$video' => t('Insert Vorbis [.ogg] video'),
- '$audio' => t('Insert Vorbis [.ogg] audio'),
- '$setloc' => t('Set your location'),
- '$noloc' => t('Clear browser location'),
- '$wait' => t('Please wait'),
- '$permset' => t('Permission settings'),
- '$ptyp' => $itm[0]['type'],
- '$content' => undo_post_tagging($itm[0]['body']),
- '$post_id' => $post_id,
- '$baseurl' => z_root(),
- '$defloc' => $channel['channel_location'],
- '$visitor' => false,
- '$public' => t('Public post'),
- '$jotnets' => $jotnets,
- '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
- '$placeholdertitle' => t('Layout Description (Optional)'),
- '$pagetitle' => $layout_title,
- '$placeholdpagetitle' => t('Layout Name'),
- '$category' => '',
- '$placeholdercategory' => t('Categories (optional, comma-separated list)'),
- '$emtitle' => t('Example: bob@example.com, mary@example.com'),
- '$lockstate' => $lockstate,
- '$acl' => '',
- '$bang' => '',
- '$profile_uid' => (intval($owner)),
- '$jotplugins' => $jotplugins,
- '$sourceapp' => t(App::$sourcename),
- '$defexpire' => '',
- '$feature_expire' => false,
- '$expires' => t('Set expiration date'),
- ));
-
-
- $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;
-
-}
-
-
diff --git a/mod/editpost.php b/mod/editpost.php
deleted file mode 100644
index ae77e5973..000000000
--- a/mod/editpost.php
+++ /dev/null
@@ -1,175 +0,0 @@
-<?php /** @file */
-
-require_once('include/acl_selectors.php');
-require_once('include/crypto.php');
-require_once('include/items.php');
-require_once('include/taxonomy.php');
-
-function editpost_content(&$a) {
-
- $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'];
-
-
- $plaintext = true;
-// if(feature_enabled(local_channel(),'richtext'))
-// $plaintext = false;
-
- $channel = App::get_channel();
-
- App::$page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array(
- '$baseurl' => z_root(),
- '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
- '$pretext' => '',
- '$ispublic' => '&nbsp;', // t('Visible to <strong>everybody</strong>'),
- '$geotag' => $geotag,
- '$nickname' => $channel['channel_address'],
- '$expireswhen' => t('Expires YYYY-MM-DD HH:MM'),
- '$confirmdelete' => t('Delete item?'),
- '$editor_autocomplete'=> true,
- '$bbco_autocomplete'=> 'bbcode'
- ));
-
- 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);
- }
-
- $tpl = get_markup_template("jot.tpl");
-
- $jotplugins = '';
- $jotnets = '';
-
- call_hooks('jot_tool', $jotplugins);
- call_hooks('jot_networks', $jotnets);
-
- //$tpl = replace_macros($tpl,array('$jotplugins' => $jotplugins));
-
- $voting = feature_enabled($owner_uid,'consensus_tools');
-
- $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";
- }
- }
- }
-
- $cipher = get_pconfig(App::$profile['profile_uid'],'system','default_cipher');
- if(! $cipher)
- $cipher = 'aes256';
-
-
- $editor = replace_macros($tpl,array(
- '$return_path' => $_SESSION['return_url'],
- '$action' => 'item',
- '$share' => t('Edit'),
- '$bold' => t('Bold'),
- '$italic' => t('Italic'),
- '$underline' => t('Underline'),
- '$quote' => t('Quote'),
- '$code' => t('Code'),
- '$upload' => t('Upload photo'),
- '$attach' => t('Attach file'),
- '$weblink' => t('Insert web link'),
- '$youtube' => t('Insert YouTube video'),
- '$video' => t('Insert Vorbis [.ogg] video'),
- '$audio' => t('Insert Vorbis [.ogg] audio'),
- '$setloc' => t('Set your location'),
- '$noloc' => t('Clear browser location'),
- '$voting' => t('Toggle voting'),
- '$feature_voting' => $voting,
- '$consensus' => intval($itm[0]['item_consensus']),
- '$wait' => t('Please wait'),
- '$permset' => t('Permission settings'),
- '$ptyp' => $itm[0]['obj_type'],
- '$content' => undo_post_tagging($itm[0]['body']),
- '$post_id' => $post_id,
- '$parent' => (($itm[0]['parent'] != $itm[0]['id']) ? $itm[0]['parent'] : ''),
- '$baseurl' => z_root(),
- '$defloc' => $channel['channel_location'],
- '$visitor' => false,
- '$public' => t('Public post'),
- '$jotnets' => $jotnets,
- '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
- '$placeholdertitle' => t('Title (optional)'),
- '$category' => $category,
- '$placeholdercategory' => t('Categories (optional, comma-separated list)'),
- '$emtitle' => t('Example: bob@example.com, mary@example.com'),
- '$lockstate' => $lockstate,
- '$acl' => '',
- '$bang' => '',
- '$profile_uid' => $owner_uid,
- '$preview' => t('Preview'),
- '$jotplugins' => $jotplugins,
- '$sourceapp' => t(App::$sourcename),
- '$catsenabled' => $catsenabled,
- '$defexpire' => datetime_convert('UTC', date_default_timezone_get(),$itm[0]['expires']),
- '$feature_expire' => ((feature_enabled(App::$profile['profile_uid'],'content_expire') && (! $webpage)) ? true : false),
- '$expires' => t('Set expiration date'),
- '$feature_encrypt' => ((feature_enabled(App::$profile['profile_uid'],'content_encrypt') && (! $webpage)) ? true : false),
- '$encrypt' => t('Encrypt text'),
- '$cipher' => $cipher,
- '$expiryModalOK' => t('OK'),
- '$expiryModalCANCEL' => t('Cancel'),
- '$bbcode' => true
- ));
-
- $o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
- '$title' => t('Edit post'),
- '$editor' => $editor
- ));
-
- return $o;
-
-}
-
-
diff --git a/mod/editwebpage.php b/mod/editwebpage.php
deleted file mode 100644
index 7cf738989..000000000
--- a/mod/editwebpage.php
+++ /dev/null
@@ -1,233 +0,0 @@
-<?php
-
-require_once('include/identity.php');
-require_once('include/acl_selectors.php');
-
-function editwebpage_init(&$a) {
-
- 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 editwebpage_content(&$a) {
-
- 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'];
-
- $plaintext = true;
-
- $mimetype = $itm[0]['mimetype'];
-
- if($mimetype === 'application/x-php') {
- if((! $uid) || ($uid != $itm[0]['uid'])) {
- notice( t('Permission denied.') . EOL);
- return;
- }
- }
-
- $mimeselect = '';
-
- if($mimetype != 'text/bbcode')
- $plaintext = true;
-
- if(get_config('system','page_mimetype'))
- $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />';
- else
- $mimeselect = mimetype_select($itm[0]['uid'],$mimetype);
-
- $layout = get_config('system','page_layout');
- if($layout)
- $layoutselect = '<input type="hidden" name="layout_mid" value="' . $layout . '" />';
- else
- $layoutselect = layout_select($itm[0]['uid'],$itm[0]['layout_mid']);
-
- App::$page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array(
- '$baseurl' => z_root(),
- '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
- '$pretext' => '',
- '$ispublic' => '&nbsp;', // t('Visible to <strong>everybody</strong>'),
- '$geotag' => $geotag,
- '$nickname' => $channel['channel_address'],
- '$confirmdelete' => t('Delete webpage?'),
- '$bbco_autocomplete'=> (($mimetype == 'text/bbcode') ? 'bbcode' : '')
- ));
-
- $tpl = get_markup_template("jot.tpl");
-
- $jotplugins = '';
- $jotnets = '';
-
- call_hooks('jot_tool', $jotplugins);
- call_hooks('jot_networks', $jotnets);
-
- // FIXME A return path with $_SESSION doesn't always work for observer - it may WSoD
- // instead of loading a sensible page. So, send folk to the webpage list.
-
- $rp = 'webpages/' . $which;
-
- $editor = replace_macros($tpl,array(
- '$return_path' => $rp,
- '$webpage' => ITEM_TYPE_WEBPAGE,
- '$placeholdpagetitle' => t('Page link title'),
- '$pagetitle' => $page_title,
- '$writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_storage'),
- '$action' => 'item',
- '$share' => t('Edit'),
- '$bold' => t('Bold'),
- '$italic' => t('Italic'),
- '$underline' => t('Underline'),
- '$quote' => t('Quote'),
- '$code' => t('Code'),
- '$upload' => t('Upload photo'),
- '$attach' => t('Attach file'),
- '$weblink' => t('Insert web link'),
- '$youtube' => t('Insert YouTube video'),
- '$video' => t('Insert Vorbis [.ogg] video'),
- '$audio' => t('Insert Vorbis [.ogg] audio'),
- '$setloc' => t('Set your location'),
- '$noloc' => ((get_pconfig($uid, 'system', 'use_browser_location')) ? t('Clear browser location') : ''),
- '$wait' => t('Please wait'),
- '$permset' => t('Permission settings'),
- '$ptyp' => $itm[0]['type'],
- '$content' => undo_post_tagging($itm[0]['body']),
- '$post_id' => $post_id,
- '$baseurl' => z_root(),
- '$defloc' => $itm[0]['location'],
- '$visitor' => ($is_owner) ? true : false,
- '$acl' => populate_acl($itm[0],false),
- '$showacl' => ($is_owner) ? true : false,
- '$public' => t('Public post'),
- '$jotnets' => $jotnets,
- '$mimeselect' => $mimeselect,
- '$layoutselect' => $layoutselect,
- '$title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
- '$placeholdertitle' => t('Title (optional)'),
- '$category' => '',
- '$placeholdercategory' => t('Categories (optional, comma-separated list)'),
- '$emtitle' => t('Example: bob@example.com, mary@example.com'),
- 'lockstate' => (((strlen($itm[0]['allow_cid'])) || (strlen($itm[0]['allow_gid'])) || (strlen($itm[0]['deny_cid'])) || (strlen($itm[0]['deny_gid']))) ? 'lock' : 'unlock'),
- '$bang' => '',
- '$profile_uid' => (intval($owner)),
- '$preview' => t('Preview'),
- '$jotplugins' => $jotplugins,
- '$sourceapp' => App::$sourcename,
- '$defexpire' => '',
- '$feature_expire' => false,
- '$expires' => t('Set expiration date'),
- '$bbcode' => (($mimetype == 'text/bbcode') ? true : false)
- ));
-
- $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;
-
-}
-
-
diff --git a/mod/events.php b/mod/events.php
deleted file mode 100755
index 30cf5f303..000000000
--- a/mod/events.php
+++ /dev/null
@@ -1,708 +0,0 @@
-<?php
-
-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');
-
-function events_post(&$a) {
-
- 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 events_content(&$a) {
-
- 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'),
- '$acl' => (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults),false)),
- '$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');
- }
- }
-
-}
diff --git a/mod/fbrowser.php b/mod/fbrowser.php
deleted file mode 100644
index 96e0fe953..000000000
--- a/mod/fbrowser.php
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-/**
- * @package Friendica\modules
- * @subpackage FileBrowser
- * @author Fabio Comuni <fabrixxm@kirgroup.com>
- */
-
-require_once('include/photo/photo_driver.php');
-
-/**
- * @param App $a
- */
-function fbrowser_content($a){
-
- 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..
- function folder1($el){return array(bin2hex($el['album']),$el['album']);}
- $albums = array_map( "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())
- );
-
- function files1($rr){
- global $a;
- $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
- );
- }
- $files = array_map("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())
- );
-
- function files2($rr){ global $a;
- 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');
- }
- $files = array_map("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();
-
-}
diff --git a/mod/feed.php b/mod/feed.php
deleted file mode 100644
index 087d3f827..000000000
--- a/mod/feed.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-
-require_once('include/items.php');
-
-function feed_init(&$a) {
-
- $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();
- }
-
-}
-
-
diff --git a/mod/ffsapi.php b/mod/ffsapi.php
deleted file mode 100644
index 1f68a87ba..000000000
--- a/mod/ffsapi.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-
-function ffsapi_content(&$a) {
-
-$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;
-
-}
diff --git a/mod/fhublocs.php b/mod/fhublocs.php
deleted file mode 100644
index 7eab2b811..000000000
--- a/mod/fhublocs.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-
-require_once('include/zot.php');
-require_once('include/crypto.php');
-
-/* fix missing or damaged hublocs */
-
-function fhublocs_content(&$a) {
-
- 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;
-
- }
-} \ No newline at end of file
diff --git a/mod/filer.php b/mod/filer.php
deleted file mode 100644
index b09c73f0a..000000000
--- a/mod/filer.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-require_once('include/security.php');
-require_once('include/bbcode.php');
-require_once('include/items.php');
-
-
-function filer_content(&$a) {
-
- 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();
-}
diff --git a/mod/filerm.php b/mod/filerm.php
deleted file mode 100644
index 82eed83f8..000000000
--- a/mod/filerm.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-function filerm_content(&$a) {
-
- 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();
-}
diff --git a/mod/filestorage.php b/mod/filestorage.php
deleted file mode 100644
index 1feffa9ee..000000000
--- a/mod/filestorage.php
+++ /dev/null
@@ -1,167 +0,0 @@
-<?php
-/**
- * @file mod/filestorage.php
- *
- */
-
-require_once('include/attach.php');
-
-/**
- *
- * @param object &$a
- */
-function filestorage_post(&$a) {
-
- $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 filestorage_content(&$a) {
-
- 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);
- $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);
-}
diff --git a/mod/follow.php b/mod/follow.php
deleted file mode 100644
index 207a99dd7..000000000
--- a/mod/follow.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-
-require_once('include/follow.php');
-
-function follow_init(&$a) {
-
- 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();
-
- $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 follow_content(&$a) {
-
- if(! local_channel()) {
- return login();
- }
-} \ No newline at end of file
diff --git a/mod/fsuggest.php b/mod/fsuggest.php
deleted file mode 100644
index 261679e6b..000000000
--- a/mod/fsuggest.php
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-
-
-function fsuggest_post(&$a) {
-
- 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 fsuggest_content(&$a) {
-
- 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;
-} \ No newline at end of file
diff --git a/mod/getfile.php b/mod/getfile.php
deleted file mode 100644
index c0916de79..000000000
--- a/mod/getfile.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-
-/**
- * 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');
-
-function getfile_post(&$a) {
-
- $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();
-
-
-
-} \ No newline at end of file
diff --git a/mod/group.php b/mod/group.php
deleted file mode 100644
index d5f2129bd..000000000
--- a/mod/group.php
+++ /dev/null
@@ -1,238 +0,0 @@
-<?php
-
-require_once('include/group.php');
-
-
-function group_post(&$a) {
-
- 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 group_content(&$a) {
- $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);
-
-}
-
diff --git a/mod/hcard.php b/mod/hcard.php
deleted file mode 100644
index 9954e0838..000000000
--- a/mod/hcard.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-function hcard_init(&$a) {
-
- 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 hcard_content(&$a) {
-
- require_once('include/widgets.php');
- return widget_profile(array());
-
-
-
-}
-
-
diff --git a/mod/help.php b/mod/help.php
deleted file mode 100644
index fb0339cd9..000000000
--- a/mod/help.php
+++ /dev/null
@@ -1,281 +0,0 @@
-<?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.
- *
- */
-
-
-
-function load_doc_file($s) {
- $lang = App::$language;
- if(! isset($lang))
- $lang = 'en';
- $b = basename($s);
- $d = dirname($s);
-
- $c = find_doc_file("$d/$lang/$b");
- if($c)
- return $c;
- $c = find_doc_file($s);
- if($c)
- return $c;
- return '';
-}
-
-function find_doc_file($s) {
- if(file_exists($s))
- return file_get_contents($s);
- return '';
-}
-
-function search_doc_files($s) {
-
- $a = get_app();
-
- $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']));
-
- $regexop = db_getfunc('REGEXP');
-
- $r = q("select item_id.sid, item.* from item left join item_id on item.id = item_id.iid where service = 'docfile' and
- body $regexop '%s' and item_type = %d $pager_sql",
- dbesc($s),
- intval(ITEM_TYPE_DOC)
- );
-
- $r = fetch_post_tags($r,true);
-
- for($x = 0; $x < count($r); $x ++) {
-
- $r[$x]['text'] = $r[$x]['body'];
-
- $r[$x]['rank'] = 0;
- if($r[$x]['term']) {
- foreach($r[$x]['term'] as $t) {
- if(stristr($t['term'],$s)) {
- $r[$x]['rank'] ++;
- }
- }
- }
- if(stristr($r[$x]['sid'],$s))
- $r[$x]['rank'] ++;
- $r[$x]['rank'] += substr_count(strtolower($r[$x]['text']),strtolower($s));
- // bias the results to the observer's native language
- if($r[$x]['lang'] === App::$language)
- $r[$x]['rank'] = $r[$x]['rank'] + 10;
-
- }
- usort($r,'doc_rank_sort');
- return $r;
-}
-
-
-function doc_rank_sort($s1,$s2) {
- if($s1['rank'] == $s2['rank'])
- return 0;
- return (($s1['rank'] < $s2['rank']) ? 1 : (-1));
-}
-
-
-function load_context_help() {
-
- $path = App::$cmd;
- $args = App::$argv;
-
- while($path) {
- $context_help = load_doc_file('doc/context/' . $path . '/help.html');
- if($context_help)
- break;
- array_pop($args);
- $path = implode($args,'/');
- }
-
- return $context_help;
-}
-
-
-function store_doc_file($s) {
-
- if(is_dir($s))
- return;
-
- $item = array();
- $sys = get_sys_channel();
-
- $item['aid'] = 0;
- $item['uid'] = $sys['channel_id'];
-
-
- if(strpos($s,'.md'))
- $mimetype = 'text/markdown';
- elseif(strpos($s,'.html'))
- $mimetype = 'text/html';
- else
- $mimetype = 'text/bbcode';
-
- require_once('include/html2plain.php');
-
- $item['body'] = html2plain(prepare_text(file_get_contents($s),$mimetype, true));
- $item['mimetype'] = 'text/plain';
-
- $item['plink'] = z_root() . '/' . str_replace('doc','help',$s);
- $item['owner_xchan'] = $item['author_xchan'] = $sys['channel_hash'];
- $item['item_type'] = ITEM_TYPE_DOC;
-
- $r = q("select item.* from item left join item_id on item.id = item_id.iid where service = 'docfile' and
- sid = '%s' and item_type = %d limit 1",
- dbesc($s),
- intval(ITEM_TYPE_DOC)
- );
-
- if($r) {
- $item['id'] = $r[0]['id'];
- $item['mid'] = $item['parent_mid'] = $r[0]['mid'];
- $x = item_store_update($item);
- }
- else {
- $item['mid'] = $item['parent_mid'] = item_message_id();
- $x = item_store($item);
- }
-
- if($x['success']) {
- update_remote_id($sys,$x['item_id'],ITEM_TYPE_DOC,$s,'docfile',0,$item['mid']);
- }
-
-
-}
-
-
-function help_content(&$a) {
- 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", 'preg_callback_help_include', $content);
-
- return replace_macros(get_markup_template("help.tpl"), array(
- '$title' => t('$Projectname Documentation'),
- '$content' => translate_projectname($content)
- ));
-
-}
-
-
-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;
- }
-
-}
-
diff --git a/mod/home.php b/mod/home.php
deleted file mode 100644
index 478c764ea..000000000
--- a/mod/home.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-require_once('include/items.php');
-require_once('include/conversation.php');
-
-
-function home_init(&$a) {
-
- $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 home_content(&$a, $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;
-
-}
diff --git a/mod/hostxrd.php b/mod/hostxrd.php
deleted file mode 100644
index 0e19d8af6..000000000
--- a/mod/hostxrd.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-function hostxrd_init(&$a) {
- 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();
-}
diff --git a/mod/id.php b/mod/id.php
deleted file mode 100644
index 382df45d8..000000000
--- a/mod/id.php
+++ /dev/null
@@ -1,310 +0,0 @@
-<?php
-/**
- * @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
- */
-function id_init(&$a) {
-
- 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
- */
-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 echo $handle?>">
-* Login: <input type="text" name="login"><br>
-* Password: <input type="password" name="password"><br>
-* <button>Submit</button>
-* </form>
-* <?php
-* 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 = 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 = 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');
- }
-}
diff --git a/mod/impel.php b/mod/impel.php
deleted file mode 100644
index a0cb1d949..000000000
--- a/mod/impel.php
+++ /dev/null
@@ -1,201 +0,0 @@
-<?php /** @file */
-
-// import page design element
-
-require_once('include/menu.php');
-
-function impel_init(&$a) {
-
- $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);
-
-}
diff --git a/mod/import.php b/mod/import.php
deleted file mode 100644
index b14b97777..000000000
--- a/mod/import.php
+++ /dev/null
@@ -1,547 +0,0 @@
-<?php
-
-// 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');
-
-
-function import_account(&$a, $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 import_post(&$a) {
-
- $account_id = get_account_id();
- if(! $account_id)
- return;
-
- import_account($a, $account_id);
-}
-
-function import_content(&$a) {
-
- 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;
-
-}
diff --git a/mod/import_items.php b/mod/import_items.php
deleted file mode 100644
index df3afb3ea..000000000
--- a/mod/import_items.php
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-
-require_once('include/import.php');
-
-function import_items_post(&$a) {
-
- 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 import_items_content(&$a) {
-
- 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;
-
-}
-
-
diff --git a/mod/invite.php b/mod/invite.php
deleted file mode 100644
index 2adad8257..000000000
--- a/mod/invite.php
+++ /dev/null
@@ -1,146 +0,0 @@
-<?php
-
-/**
- * module: invite.php
- *
- * send email invitations to join social network
- *
- */
-
-function invite_post(&$a) {
-
- 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 invite_content(&$a) {
-
- 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;
-}
diff --git a/mod/item.php b/mod/item.php
deleted file mode 100644
index 6e7c77a4d..000000000
--- a/mod/item.php
+++ /dev/null
@@ -1,1262 +0,0 @@
-<?php
-
-/**
- *
- * This is the POST destination for most all locally posted
- * text stuff. This function handles status, wall-to-wall status,
- * local comments, and remote coments that are posted on this site
- * (as opposed to being delivered in a feed).
- * Also processed here are posts and comments coming through the
- * statusnet/twitter API.
- * All of these become an "item" which is our basic unit of
- * information.
- * Posts that originate externally or do not fall into the above
- * posting categories go through item_store() instead of this function.
- *
- */
-
-require_once('include/crypto.php');
-require_once('include/enotify.php');
-require_once('include/items.php');
-require_once('include/attach.php');
-
-function item_post(&$a) {
-
- // This will change. Figure out who the observer is and whether or not
- // they have permission to post here. Else ignore the post.
-
- if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'commenter')))
- return;
-
- require_once('include/security.php');
-
- $uid = local_channel();
- $channel = null;
- $observer = null;
-
-
- /**
- * Is this a reply to something?
- */
-
- $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
- $parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : '');
-
- $remote_xchan = ((x($_REQUEST,'remote_xchan')) ? trim($_REQUEST['remote_xchan']) : false);
- $r = q("select * from xchan where xchan_hash = '%s' limit 1",
- dbesc($remote_xchan)
- );
- if($r)
- $remote_observer = $r[0];
- else
- $remote_xchan = $remote_observer = false;
-
- $profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0);
- require_once('include/identity.php');
- $sys = get_sys_channel();
- if($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) {
- $uid = intval($sys['channel_id']);
- $channel = $sys;
- $observer = $sys;
- }
-
- if(x($_REQUEST,'dropitems')) {
- require_once('include/items.php');
- $arr_drop = explode(',',$_REQUEST['dropitems']);
- drop_items($arr_drop);
- $json = array('success' => 1);
- echo json_encode($json);
- killme();
- }
-
- call_hooks('post_local_start', $_REQUEST);
-
-// logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
-
- $api_source = ((x($_REQUEST,'api_source') && $_REQUEST['api_source']) ? true : false);
-
- $consensus = intval($_REQUEST['consensus']);
-
- // 'origin' (if non-zero) indicates that this network is where the message originated,
- // for the purpose of relaying comments to other conversation members.
- // If using the API from a device (leaf node) you must set origin to 1 (default) or leave unset.
- // If the API is used from another network with its own distribution
- // and deliveries, you may wish to set origin to 0 or false and allow the other
- // network to relay comments.
-
- // If you are unsure, it is prudent (and important) to leave it unset.
-
- $origin = (($api_source && array_key_exists('origin',$_REQUEST)) ? intval($_REQUEST['origin']) : 1);
-
- // To represent message-ids on other networks - this will create an item_id record
-
- $namespace = (($api_source && array_key_exists('namespace',$_REQUEST)) ? strip_tags($_REQUEST['namespace']) : '');
- $remote_id = (($api_source && array_key_exists('remote_id',$_REQUEST)) ? strip_tags($_REQUEST['remote_id']) : '');
-
- $owner_hash = null;
-
- $message_id = ((x($_REQUEST,'message_id') && $api_source) ? strip_tags($_REQUEST['message_id']) : '');
- $created = ((x($_REQUEST,'created')) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['created']) : datetime_convert());
- $post_id = ((x($_REQUEST,'post_id')) ? intval($_REQUEST['post_id']) : 0);
- $app = ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : '');
- $return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : '');
- $preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0);
- $categories = ((x($_REQUEST,'category')) ? escape_tags($_REQUEST['category']) : '');
- $webpage = ((x($_REQUEST,'webpage')) ? intval($_REQUEST['webpage']) : 0);
- $pagetitle = ((x($_REQUEST,'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : '');
- $layout_mid = ((x($_REQUEST,'layout_mid')) ? escape_tags($_REQUEST['layout_mid']): '');
- $plink = ((x($_REQUEST,'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
- $obj_type = ((x($_REQUEST,'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE);
-
- // allow API to bulk load a bunch of imported items with sending out a bunch of posts.
- $nopush = ((x($_REQUEST,'nopush')) ? intval($_REQUEST['nopush']) : 0);
-
- /*
- * Check service class limits
- */
- if ($uid && !(x($_REQUEST,'parent')) && !(x($_REQUEST,'post_id'))) {
- $ret = item_check_service_class($uid,(($_REQUEST['webpage'] == ITEM_TYPE_WEBPAGE) ? true : false));
- if (!$ret['success']) {
- notice( t($ret['message']) . EOL) ;
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
- killme();
- }
- }
-
- if($pagetitle) {
- require_once('library/urlify/URLify.php');
- $pagetitle = strtolower(URLify::transliterate($pagetitle));
- }
-
-
- $item_flags = $item_restrict = 0;
-
- $route = '';
- $parent_item = null;
- $parent_contact = null;
- $thr_parent = '';
- $parid = 0;
- $r = false;
-
- if($parent || $parent_mid) {
-
- if(! x($_REQUEST,'type'))
- $_REQUEST['type'] = 'net-comment';
-
- if($obj_type == ACTIVITY_OBJ_POST)
- $obj_type = ACTIVITY_OBJ_COMMENT;
-
- if($parent) {
- $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1",
- intval($parent)
- );
- }
- elseif($parent_mid && $uid) {
- // This is coming from an API source, and we are logged in
- $r = q("SELECT * FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1",
- dbesc($parent_mid),
- intval($uid)
- );
- }
- // if this isn't the real parent of the conversation, find it
- if($r !== false && count($r)) {
- $parid = $r[0]['parent'];
- $parent_mid = $r[0]['mid'];
- if($r[0]['id'] != $r[0]['parent']) {
- $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1",
- intval($parid)
- );
- }
- }
-
- if(($r === false) || (! count($r))) {
- notice( t('Unable to locate original post.') . EOL);
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
- killme();
- }
-
- // can_comment_on_post() needs info from the following xchan_query
- xchan_query($r);
-
- $parent_item = $r[0];
- $parent = $r[0]['id'];
-
- // multi-level threading - preserve the info but re-parent to our single level threading
-
- $thr_parent = $parent_mid;
-
- $route = $parent_item['route'];
-
- }
-
- if(! $observer)
- $observer = App::get_observer();
-
- if($parent) {
- logger('mod_item: item_post parent=' . $parent);
- $can_comment = false;
- if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self']))
- $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments');
- else
- $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item);
-
- if(! $can_comment) {
- notice( t('Permission denied.') . EOL) ;
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
- killme();
- }
- }
- else {
- if(! perm_is_allowed($profile_uid,$observer['xchan_hash'],($webpage) ? 'write_pages' : 'post_wall')) {
- notice( t('Permission denied.') . EOL) ;
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
- killme();
- }
- }
-
-
- // is this an edited post?
-
- $orig_post = null;
-
- if($namespace && $remote_id) {
- // It wasn't an internally generated post - see if we've got an item matching this remote service id
- $i = q("select iid from item_id where service = '%s' and sid = '%s' limit 1",
- dbesc($namespace),
- dbesc($remote_id)
- );
- if($i)
- $post_id = $i[0]['iid'];
- }
-
- $iconfig = null;
-
- if($post_id) {
- $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1",
- intval($profile_uid),
- intval($post_id)
- );
- if(! count($i))
- killme();
- $orig_post = $i[0];
- $iconfig = q("select * from iconfig where iid = %d",
- intval($post_id)
- );
- }
-
-
- if(! $channel) {
- if($uid && $uid == $profile_uid) {
- $channel = App::get_channel();
- }
- else {
- // posting as yourself but not necessarily to a channel you control
- $r = q("select * from channel left join account on channel_account_id = account_id where channel_id = %d LIMIT 1",
- intval($profile_uid)
- );
- if($r)
- $channel = $r[0];
- }
- }
-
-
- if(! $channel) {
- logger("mod_item: no channel.");
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
- killme();
- }
-
- $owner_xchan = null;
-
- $r = q("select * from xchan where xchan_hash = '%s' limit 1",
- dbesc($channel['channel_hash'])
- );
- if($r && count($r)) {
- $owner_xchan = $r[0];
- }
- else {
- logger("mod_item: no owner.");
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
- killme();
- }
-
- $walltowall = false;
- $walltowall_comment = false;
-
- if($remote_xchan)
- $observer = $remote_observer;
-
- if($observer) {
- logger('mod_item: post accepted from ' . $observer['xchan_name'] . ' for ' . $owner_xchan['xchan_name'], LOGGER_DEBUG);
-
- // wall-to-wall detection.
- // For top-level posts, if the author and owner are different it's a wall-to-wall
- // For comments, We need to additionally look at the parent and see if it's a wall post that originated locally.
-
- if($observer['xchan_name'] != $owner_xchan['xchan_name']) {
- if(($parent_item) && ($parent_item['item_wall'] && $parent_item['item_origin'])) {
- $walltowall_comment = true;
- $walltowall = true;
- }
- if(! $parent) {
- $walltowall = true;
- }
- }
- }
-
- $acl = new Zotlabs\Access\AccessList($channel);
-
-
- $public_policy = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($channel['channel_r_stream'],true));
- if($webpage)
- $public_policy = '';
- if($public_policy)
- $private = 1;
-
- if($orig_post) {
- $private = 0;
- // webpages are allowed to change ACLs after the fact. Normal conversation items aren't.
- if($webpage) {
- $acl->set_from_array($_REQUEST);
- }
- else {
- $acl->set($orig_post);
- $public_policy = $orig_post['public_policy'];
- $private = $orig_post['item_private'];
- }
-
- if($private || $public_policy || $acl->is_private())
- $private = 1;
-
-
- $location = $orig_post['location'];
- $coord = $orig_post['coord'];
- $verb = $orig_post['verb'];
- $app = $orig_post['app'];
- $title = escape_tags(trim($_REQUEST['title']));
- $body = trim($_REQUEST['body']);
- $item_flags = $orig_post['item_flags'];
-
- $item_origin = $orig_post['item_origin'];
- $item_unseen = $orig_post['item_unseen'];
- $item_starred = $orig_post['item_starred'];
- $item_uplink = $orig_post['item_uplink'];
- $item_consensus = $orig_post['item_consensus'];
- $item_wall = $orig_post['item_wall'];
- $item_thread_top = $orig_post['item_thread_top'];
- $item_notshown = $orig_post['item_notshown'];
- $item_nsfw = $orig_post['item_nsfw'];
- $item_relay = $orig_post['item_relay'];
- $item_mentionsme = $orig_post['item_mentionsme'];
- $item_nocomment = $orig_post['item_nocomment'];
- $item_obscured = $orig_post['item_obscured'];
- $item_verified = $orig_post['item_verified'];
- $item_retained = $orig_post['item_retained'];
- $item_rss = $orig_post['item_rss'];
- $item_deleted = $orig_post['item_deleted'];
- $item_type = $orig_post['item_type'];
- $item_hidden = $orig_post['item_hidden'];
- $item_unpublished = $orig_post['item_unpublished'];
- $item_delayed = $orig_post['item_delayed'];
- $item_pending_remove = $orig_post['item_pending_remove'];
- $item_blocked = $orig_post['item_blocked'];
-
-
-
- $postopts = $orig_post['postopts'];
- $created = $orig_post['created'];
- $mid = $orig_post['mid'];
- $parent_mid = $orig_post['parent_mid'];
- $plink = $orig_post['plink'];
-
- }
- else {
- if(! $walltowall) {
- if((array_key_exists('contact_allow',$_REQUEST))
- || (array_key_exists('group_allow',$_REQUEST))
- || (array_key_exists('contact_deny',$_REQUEST))
- || (array_key_exists('group_deny',$_REQUEST))) {
- $acl->set_from_array($_REQUEST);
- }
- elseif(! $api_source) {
-
- // if no ACL has been defined and we aren't using the API, the form
- // didn't send us any parameters. This means there's no ACL or it has
- // been reset to the default audience.
- // If $api_source is set and there are no ACL parameters, we default
- // to the channel permissions which were set in the ACL contructor.
-
- $acl->set(array('allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''));
- }
- }
-
-
- $location = notags(trim($_REQUEST['location']));
- $coord = notags(trim($_REQUEST['coord']));
- $verb = notags(trim($_REQUEST['verb']));
- $title = escape_tags(trim($_REQUEST['title']));
- $body = trim($_REQUEST['body']);
- $body .= trim($_REQUEST['attachment']);
- $postopts = '';
-
- $private = intval($acl->is_private() || ($public_policy));
-
- // If this is a comment, set the permissions from the parent.
-
- if($parent_item) {
- $private = 0;
- $acl->set($parent_item);
- $private = intval($acl->is_private() || $parent_item['item_private']);
- $public_policy = $parent_item['public_policy'];
- $owner_hash = $parent_item['owner_xchan'];
- }
-
- if(! strlen($body)) {
- if($preview)
- killme();
- info( t('Empty post discarded.') . EOL );
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
- killme();
- }
- }
-
-
- $expires = NULL_DATE;
-
- if(feature_enabled($profile_uid,'content_expire')) {
- if(x($_REQUEST,'expire')) {
- $expires = datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expire']);
- if($expires <= datetime_convert())
- $expires = NULL_DATE;
- }
- }
-
- $mimetype = notags(trim($_REQUEST['mimetype']));
- if(! $mimetype)
- $mimetype = 'text/bbcode';
-
- if($preview) {
- $body = z_input_filter($profile_uid,$body,$mimetype);
- }
-
-
- // Verify ability to use html or php!!!
-
- $execflag = false;
-
- if($mimetype !== 'text/bbcode') {
- $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($profile_uid)
- );
- if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) {
- if($uid && (get_account_id() == $z[0]['account_id'])) {
- $execflag = true;
- }
- else {
- notice( t('Executable content type not permitted to this channel.') . EOL);
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
- killme();
- }
- }
- }
-
- $gacl = $acl->get();
- $str_contact_allow = $gacl['allow_cid'];
- $str_group_allow = $gacl['allow_gid'];
- $str_contact_deny = $gacl['deny_cid'];
- $str_group_deny = $gacl['deny_gid'];
-
- if($mimetype === 'text/bbcode') {
-
- require_once('include/text.php');
-
- // Markdown doesn't work correctly. Do not re-enable unless you're willing to fix it and support it.
-
- // Sample that will probably give you grief - you must preserve the linebreaks
- // and provide the correct markdown interpretation and you cannot allow unfiltered HTML
-
- // Markdown
- // ========
- //
- // **bold** abcde
- // fghijkl
- // *italic*
- // <img src="javascript:alert('hacked');" />
-
-// if($uid && $uid == $profile_uid && feature_enabled($uid,'markdown')) {
-// require_once('include/bb2diaspora.php');
-// $body = escape_tags(trim($body));
-// $body = str_replace("\n",'<br />', $body);
-// $body = preg_replace_callback('/\[share(.*?)\]/ism','share_shield',$body);
-// $body = diaspora2bb($body,true);
-// $body = preg_replace_callback('/\[share(.*?)\]/ism','share_unshield',$body);
-// }
-
- // BBCODE alert: the following functions assume bbcode input
- // and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
- // we may need virtual or template classes to implement the possible alternatives
-
- // Work around doubled linefeeds in Tinymce 3.5b2
- // First figure out if it's a status post that would've been
- // created using tinymce. Otherwise leave it alone.
-
- $plaintext = true;
-
-// $plaintext = ((feature_enabled($profile_uid,'richtext')) ? false : true);
-// if((! $parent) && (! $api_source) && (! $plaintext)) {
-// $body = fix_mce_lf($body);
-// }
-
-
-
- // If we're sending a private top-level message with a single @-taggable channel as a recipient, @-tag it, if our pconfig is set.
-
-
- if((! $parent) && (get_pconfig($profile_uid,'system','tagifonlyrecip')) && (substr_count($str_contact_allow,'<') == 1) && ($str_group_allow == '') && ($str_contact_deny == '') && ($str_group_deny == '')) {
- $x = q("select abook_id, abook_their_perms from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
- dbesc(str_replace(array('<','>'),array('',''),$str_contact_allow)),
- intval($profile_uid)
- );
- if($x && ($x[0]['abook_their_perms'] & PERMS_W_TAGWALL))
- $body .= "\n\n@group+" . $x[0]['abook_id'] . "\n";
- }
-
- /**
- * fix naked links by passing through a callback to see if this is a red site
- * (already known to us) which will get a zrl, otherwise link with url, add bookmark tag to both.
- * First protect any url inside certain bbcode tags so we don't double link it.
- */
-
-
- $body = preg_replace_callback('/\[code(.*?)\[\/(code)\]/ism','red_escape_codeblock',$body);
- $body = preg_replace_callback('/\[url(.*?)\[\/(url)\]/ism','red_escape_codeblock',$body);
- $body = preg_replace_callback('/\[zrl(.*?)\[\/(zrl)\]/ism','red_escape_codeblock',$body);
-
- $body = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,]+)/ism", 'red_zrl_callback', $body);
-
- $body = preg_replace_callback('/\[\$b64zrl(.*?)\[\/(zrl)\]/ism','red_unescape_codeblock',$body);
- $body = preg_replace_callback('/\[\$b64url(.*?)\[\/(url)\]/ism','red_unescape_codeblock',$body);
- $body = preg_replace_callback('/\[\$b64code(.*?)\[\/(code)\]/ism','red_unescape_codeblock',$body);
-
-
- // fix any img tags that should be zmg
-
- $body = preg_replace_callback('/\[img(.*?)\](.*?)\[\/img\]/ism','red_zrlify_img_callback',$body);
-
-
- $body = bb_translate_video($body);
-
- /**
- * Fold multi-line [code] sequences
- */
-
- $body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body);
-
- $body = scale_external_images($body,false);
-
-
- // Look for tags and linkify them
- $results = linkify_tags($a, $body, ($uid) ? $uid : $profile_uid);
-
- if($results) {
-
- // Set permissions based on tag replacements
- set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item, $private);
-
- $post_tags = array();
- foreach($results as $result) {
- $success = $result['success'];
- if($success['replaced']) {
- $post_tags[] = array(
- 'uid' => $profile_uid,
- 'type' => $success['termtype'],
- 'otype' => TERM_OBJ_POST,
- 'term' => $success['term'],
- 'url' => $success['url']
- );
- }
- }
- }
-
-
- /**
- *
- * When a photo was uploaded into the message using the (profile wall) ajax
- * uploader, The permissions are initially set to disallow anybody but the
- * owner from seeing it. This is because the permissions may not yet have been
- * set for the post. If it's private, the photo permissions should be set
- * appropriately. But we didn't know the final permissions on the post until
- * now. So now we'll look for links of uploaded photos and attachments that are in the
- * post and set them to the same permissions as the post itself.
- *
- * If the post was end-to-end encrypted we can't find images and attachments in the body,
- * use our media_str input instead which only contains these elements - but only do this
- * when encrypted content exists because the photo/attachment may have been removed from
- * the post and we should keep it private. If it's encrypted we have no way of knowing
- * so we'll set the permissions regardless and realise that the media may not be
- * referenced in the post.
- *
- * What is preventing us from being able to upload photos into comments is dealing with
- * the photo and attachment permissions, since we don't always know who was in the
- * distribution for the top level post.
- *
- * We might be able to provide this functionality with a lot of fiddling:
- * - if the top level post is public (make the photo public)
- * - if the top level post was written by us or a wall post that belongs to us (match the top level post)
- * - if the top level post has privacy mentions, add those to the permissions.
- * - otherwise disallow the photo *or* make the photo public. This is the part that gets messy.
- */
-
- if(! $preview) {
- fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
-
- fix_attached_file_permissions($channel,$observer['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
-
- }
-
-
- $attachments = '';
- $match = false;
-
- if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
- $attachments = array();
- $i = 0;
- foreach($match[2] as $mtch) {
- $attach_link = '';
- $hash = substr($mtch,0,strpos($mtch,','));
- $rev = intval(substr($mtch,strpos($mtch,',')));
- $r = attach_by_hash_nodata($hash,$rev);
- if($r['success']) {
- $attachments[] = array(
- 'href' => z_root() . '/attach/' . $r['data']['hash'],
- 'length' => $r['data']['filesize'],
- 'type' => $r['data']['filetype'],
- 'title' => urlencode($r['data']['filename']),
- 'revision' => $r['data']['revision']
- );
- }
- $ext = substr($r['data']['filename'],strrpos($r['data']['filename'],'.'));
- if(strpos($r['data']['filetype'],'audio/') !== false)
- $attach_link = '[audio]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . (($ext) ? $ext : '') . '[/audio]';
- elseif(strpos($r['data']['filetype'],'video/') !== false)
- $attach_link = '[video]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . (($ext) ? $ext : '') . '[/video]';
- $body = str_replace($match[1][$i],$attach_link,$body);
- $i++;
- }
- }
-
- }
-
-// BBCODE end alert
-
- 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' => $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
- );
- }
- }
-
- if($orig_post) {
- // preserve original tags
- $t = q("select * from term where oid = %d and otype = %d and uid = %d and type in ( %d, %d, %d )",
- intval($orig_post['id']),
- intval(TERM_OBJ_POST),
- intval($profile_uid),
- intval(TERM_UNKNOWN),
- intval(TERM_FILE),
- intval(TERM_COMMUNITYTAG)
- );
- if($t) {
- foreach($t as $t1) {
- $post_tags[] = array(
- 'uid' => $profile_uid,
- 'type' => $t1['type'],
- 'otype' => TERM_OBJ_POST,
- 'term' => $t1['term'],
- 'url' => $t1['url'],
- );
- }
- }
- }
-
-
- $item_unseen = ((local_channel() != $profile_uid) ? 1 : 0);
- $item_wall = (($post_type === 'wall' || $post_type === 'wall-comment') ? 1 : 0);
- $item_origin = (($origin) ? 1 : 0);
- $item_consensus = (($consensus) ? 1 : 0);
-
-
- // determine if this is a wall post
-
- if($parent) {
- $item_wall = $parent_item['item_wall'];
- }
- else {
- if(! $webpage) {
- $item_wall = 1;
- }
- }
-
-
- if($moderated)
- $item_blocked = ITEM_MODERATED;
-
-
- if(! strlen($verb))
- $verb = ACTIVITY_POST ;
-
- $notify_type = (($parent) ? 'comment-new' : 'wall-new' );
-
- if(! $mid) {
- $mid = (($message_id) ? $message_id : item_message_id());
- }
- if(! $parent_mid) {
- $parent_mid = $mid;
- }
-
- if($parent_item)
- $parent_mid = $parent_item['mid'];
-
- // Fallback so that we alway have a thr_parent
-
- if(!$thr_parent)
- $thr_parent = $mid;
-
- $datarray = array();
-
- $item_thread_top = ((! $parent) ? 1 : 0);
-
- if ((! $plink) && ($item_thread_top)) {
- $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $mid;
- }
-
-
-
-
-
- $datarray['aid'] = $channel['channel_account_id'];
- $datarray['uid'] = $profile_uid;
-
- $datarray['owner_xchan'] = (($owner_hash) ? $owner_hash : $owner_xchan['xchan_hash']);
- $datarray['author_xchan'] = $observer['xchan_hash'];
- $datarray['created'] = $created;
- $datarray['edited'] = (($orig_post) ? datetime_convert() : $created);
- $datarray['expires'] = $expires;
- $datarray['commented'] = (($orig_post) ? datetime_convert() : $created);
- $datarray['received'] = (($orig_post) ? datetime_convert() : $created);
- $datarray['changed'] = (($orig_post) ? datetime_convert() : $created);
- $datarray['mid'] = $mid;
- $datarray['parent_mid'] = $parent_mid;
- $datarray['mimetype'] = $mimetype;
- $datarray['title'] = $title;
- $datarray['body'] = $body;
- $datarray['app'] = $app;
- $datarray['location'] = $location;
- $datarray['coord'] = $coord;
- $datarray['verb'] = $verb;
- $datarray['obj_type'] = $obj_type;
- $datarray['allow_cid'] = $str_contact_allow;
- $datarray['allow_gid'] = $str_group_allow;
- $datarray['deny_cid'] = $str_contact_deny;
- $datarray['deny_gid'] = $str_group_deny;
- $datarray['item_private'] = $private;
- $datarray['item_wall'] = $item_wall;
- $datarray['attach'] = $attachments;
- $datarray['thr_parent'] = $thr_parent;
- $datarray['postopts'] = $postopts;
- $datarray['item_unseen'] = $item_unseen;
- $datarray['item_wall'] = $item_wall;
- $datarray['item_origin'] = $item_origin;
- $datarray['item_type'] = $webpage;
- $datarray['item_thread_top'] = $item_thread_top;
- $datarray['item_unseen'] = $item_unseen;
- $datarray['item_starred'] = $item_starred;
- $datarray['item_uplink'] = $item_uplink;
- $datarray['item_consensus'] = $item_consensus;
- $datarray['item_notshown'] = $item_notshown;
- $datarray['item_nsfw'] = $item_nsfw;
- $datarray['item_relay'] = $item_relay;
- $datarray['item_mentionsme'] = $item_mentionsme;
- $datarray['item_nocomment'] = $item_nocomment;
- $datarray['item_obscured'] = $item_obscured;
- $datarray['item_verified'] = $item_verified;
- $datarray['item_retained'] = $item_retained;
- $datarray['item_rss'] = $item_rss;
- $datarray['item_deleted'] = $item_deleted;
- $datarray['item_hidden'] = $item_hidden;
- $datarray['item_unpublished'] = $item_unpublished;
- $datarray['item_delayed'] = $item_delayed;
- $datarray['item_pending_remove'] = $item_pending_remove;
- $datarray['item_blocked'] = $item_blocked;
-
- $datarray['layout_mid'] = $layout_mid;
- $datarray['public_policy'] = $public_policy;
- $datarray['comment_policy'] = map_scope($channel['channel_w_comment']);
- $datarray['term'] = $post_tags;
- $datarray['plink'] = $plink;
- $datarray['route'] = $route;
-
- if($iconfig)
- $datarray['iconfig'] = $iconfig;
-
- // preview mode - prepare the body for display and send it via json
-
- if($preview) {
- require_once('include/conversation.php');
-
- $datarray['owner'] = $owner_xchan;
- $datarray['author'] = $observer;
- $datarray['attach'] = json_encode($datarray['attach']);
- $o = conversation($a,array($datarray),'search',false,'preview');
-// logger('preview: ' . $o, LOGGER_DEBUG);
- echo json_encode(array('preview' => $o));
- killme();
- }
- if($orig_post)
- $datarray['edit'] = true;
-
- if(feature_enabled($profile_uid,'suppress_duplicates') && (! $orig_post)) {
-
- $z = q("select created from item where uid = %d and body = '%s'",
- intval($profile_uid),
- dbesc($body)
- );
-
- if($z) {
- foreach($z as $zz) {
- if($zz['created'] > datetime_convert('UTC','UTC', 'now - 2 minutes')) {
- $datarray['cancel'] = 1;
- notice( t('Duplicate post suppressed.') . EOL);
- logger('Duplicate post. Faking plugin cancel.');
- }
- }
- }
- }
-
- call_hooks('post_local',$datarray);
-
- if(x($datarray,'cancel')) {
- logger('mod_item: post cancelled by plugin or duplicate suppressed.');
- if($return_path)
- goaway(z_root() . "/" . $return_path);
-
- $json = array('cancel' => 1);
- $json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
- echo json_encode($json);
- killme();
- }
-
-
- if(mb_strlen($datarray['title']) > 255)
- $datarray['title'] = mb_substr($datarray['title'],0,255);
-
- if(array_key_exists('item_private',$datarray) && $datarray['item_private']) {
-
- $datarray['body'] = trim(z_input_filter($datarray['uid'],$datarray['body'],$datarray['mimetype']));
-
- if($uid) {
- if($channel['channel_hash'] === $datarray['author_xchan']) {
- $datarray['sig'] = base64url_encode(rsa_sign($datarray['body'],$channel['channel_prvkey']));
- $datarray['item_verified'] = 1;
- }
- }
- }
-
- if($orig_post) {
- $datarray['id'] = $post_id;
-
- item_store_update($datarray,$execflag);
-
- update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid);
-
- if(! $parent) {
- $r = q("select * from item where id = %d",
- intval($post_id)
- );
- if($r) {
- xchan_query($r);
- $sync_item = fetch_post_tags($r);
- $rid = q("select * from item_id where iid = %d",
- intval($post_id)
- );
- build_sync_packet($uid,array('item' => array(encode_item($sync_item[0],true)),'item_id' => $rid));
- }
- }
- if(! $nopush)
- proc_run('php', "include/notifier.php", 'edit_post', $post_id);
-
- if((x($_REQUEST,'return')) && strlen($return_path)) {
- logger('return: ' . $return_path);
- goaway(z_root() . "/" . $return_path );
- }
- killme();
- }
- else
- $post_id = 0;
-
- $post = item_store($datarray,$execflag);
-
- $post_id = $post['item_id'];
-
- if($post_id) {
- logger('mod_item: saved item ' . $post_id);
-
- if($parent) {
-
- // only send comment notification if this is a wall-to-wall comment,
- // otherwise it will happen during delivery
-
- if(($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) {
- notification(array(
- 'type' => NOTIFY_COMMENT,
- 'from_xchan' => $datarray['author_xchan'],
- 'to_xchan' => $datarray['owner_xchan'],
- 'item' => $datarray,
- 'link' => z_root() . '/display/' . $datarray['mid'],
- 'verb' => ACTIVITY_POST,
- 'otype' => 'item',
- 'parent' => $parent,
- 'parent_mid' => $parent_item['mid']
- ));
-
- }
- }
- else {
- $parent = $post_id;
-
- if(($datarray['owner_xchan'] != $datarray['author_xchan']) && ($datarray['item_type'] == ITEM_TYPE_POST)) {
- notification(array(
- 'type' => NOTIFY_WALL,
- 'from_xchan' => $datarray['author_xchan'],
- 'to_xchan' => $datarray['owner_xchan'],
- 'item' => $datarray,
- 'link' => z_root() . '/display/' . $datarray['mid'],
- 'verb' => ACTIVITY_POST,
- 'otype' => 'item'
- ));
- }
-
- if($uid && $uid == $profile_uid && (is_item_normal($datarray))) {
- q("update channel set channel_lastpost = '%s' where channel_id = %d",
- dbesc(datetime_convert()),
- intval($uid)
- );
- }
- }
-
- // photo comments turn the corresponding item visible to the profile wall
- // This way we don't see every picture in your new photo album posted to your wall at once.
- // They will show up as people comment on them.
-
- if(intval($parent_item['item_hidden'])) {
- $r = q("UPDATE item SET item_hidden = 0 WHERE id = %d",
- intval($parent_item['id'])
- );
- }
- }
- else {
- logger('mod_item: unable to retrieve post that was just stored.');
- notice( t('System error. Post not saved.') . EOL);
- goaway(z_root() . "/" . $return_path );
- // NOTREACHED
- }
-
-
- update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid);
-
- if(($parent) && ($parent != $post_id)) {
- // Store the comment signature information in case we need to relay to Diaspora
- $ditem = $datarray;
- $ditem['author'] = $observer;
- store_diaspora_comment_sig($ditem,$channel,$parent_item, $post_id, (($walltowall_comment) ? 1 : 0));
- }
- else {
- $r = q("select * from item where id = %d",
- intval($post_id)
- );
- if($r) {
- xchan_query($r);
- $sync_item = fetch_post_tags($r);
- $rid = q("select * from item_id where iid = %d",
- intval($post_id)
- );
- build_sync_packet($uid,array('item' => array(encode_item($sync_item[0],true)),'item_id' => $rid));
- }
- }
-
- $datarray['id'] = $post_id;
- $datarray['llink'] = z_root() . '/display/' . $channel['channel_address'] . '/' . $post_id;
-
- call_hooks('post_local_end', $datarray);
-
- if(! $nopush)
- proc_run('php', 'include/notifier.php', $notify_type, $post_id);
-
- logger('post_complete');
-
-
-
-
-
-
- // figure out how to return, depending on from whence we came
-
- if($api_source)
- return $post;
-
- if($return_path) {
- goaway(z_root() . "/" . $return_path);
- }
-
- $json = array('success' => 1);
- if(x($_REQUEST,'jsreload') && strlen($_REQUEST['jsreload']))
- $json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
-
- logger('post_json: ' . print_r($json,true), LOGGER_DEBUG);
-
- echo json_encode($json);
- killme();
- // NOTREACHED
-}
-
-
-
-
-
-function item_content(&$a) {
-
- if((! local_channel()) && (! remote_channel()))
- return;
-
- require_once('include/security.php');
-
- if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
-
- require_once('include/items.php');
- $i = q("select id, uid, author_xchan, owner_xchan, source_xchan, item_type from item where id = %d limit 1",
- intval(argv(2))
- );
-
- if($i) {
- $can_delete = false;
- $local_delete = false;
- if(local_channel() && local_channel() == $i[0]['uid'])
- $local_delete = true;
-
- $sys = get_sys_channel();
- if(is_site_admin() && $sys['channel_id'] == $i[0]['uid'])
- $can_delete = true;
-
- $ob_hash = get_observer_hash();
- if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan']))
- $can_delete = true;
-
- if(! ($can_delete || $local_delete)) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- // if this is a different page type or it's just a local delete
- // but not by the item author or owner, do a simple deletion
-
- if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) {
- drop_item($i[0]['id']);
- }
- else {
- // complex deletion that needs to propagate and be performed in phases
- drop_item($i[0]['id'],true,DROPITEM_PHASE1);
- tag_deliver($i[0]['uid'],$i[0]['id']);
- }
- }
- }
-}
-
-
-function fix_attached_photo_permissions($uid,$xchan_hash,$body,
- $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny) {
-
- if(get_pconfig($uid,'system','force_public_uploads')) {
- $str_contact_allow = $str_group_allow = $str_contact_deny = $str_group_deny = '';
- }
-
- $match = null;
- // match img and zmg image links
- if(preg_match_all("/\[[zi]mg(.*?)\](.*?)\[\/[zi]mg\]/",$body,$match)) {
- $images = $match[2];
- if($images) {
- foreach($images as $image) {
- if(! stristr($image,z_root() . '/photo/'))
- continue;
- $image_uri = substr($image,strrpos($image,'/') + 1);
- if(strpos($image_uri,'-') !== false)
- $image_uri = substr($image_uri,0, strpos($image_uri,'-'));
- if(strpos($image_uri,'.') !== false)
- $image_uri = substr($image_uri,0, strpos($image_uri,'.'));
- if(! strlen($image_uri))
- continue;
- $srch = '<' . $xchan_hash . '>';
-
- $r = q("select folder from attach where hash = '%s' and uid = %d limit 1",
- dbesc($image_uri),
- intval($uid)
- );
- if($r && $r[0]['folder']) {
- $f = q("select * from attach where hash = '%s' and is_dir = 1 and uid = %d limit 1",
- dbesc($r[0]['folder']),
- intval($uid)
- );
- if(($f) && (($f[0]['allow_cid']) || ($f[0]['allow_gid']) || ($f[0]['deny_cid']) || ($f[0]['deny_gid']))) {
- $str_contact_allow = $f[0]['allow_cid'];
- $str_group_allow = $f[0]['allow_gid'];
- $str_contact_deny = $f[0]['deny_cid'];
- $str_group_deny = $f[0]['deny_gid'];
- }
- }
-
- $r = q("SELECT id FROM photo
- WHERE allow_cid = '%s' AND allow_gid = '' AND deny_cid = '' AND deny_gid = ''
- AND resource_id = '%s' AND uid = %d LIMIT 1",
- dbesc($srch),
- dbesc($image_uri),
- intval($uid)
- );
-
- if($r) {
- $r = q("UPDATE photo SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s'
- WHERE resource_id = '%s' AND uid = %d ",
- dbesc($str_contact_allow),
- dbesc($str_group_allow),
- dbesc($str_contact_deny),
- dbesc($str_group_deny),
- dbesc($image_uri),
- intval($uid)
- );
-
- // also update the linked item (which is probably invisible)
-
- $r = q("select id from item
- WHERE allow_cid = '%s' AND allow_gid = '' AND deny_cid = '' AND deny_gid = ''
- AND resource_id = '%s' and resource_type = 'photo' AND uid = %d LIMIT 1",
- dbesc($srch),
- dbesc($image_uri),
- intval($uid)
- );
- if($r) {
- $private = (($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny) ? true : false);
-
- $r = q("UPDATE item SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d
- WHERE id = %d AND uid = %d",
- dbesc($str_contact_allow),
- dbesc($str_group_allow),
- dbesc($str_contact_deny),
- dbesc($str_group_deny),
- intval($private),
- intval($r[0]['id']),
- intval($uid)
- );
- }
- $r = q("select id from attach where hash = '%s' and uid = %d limit 1",
- dbesc($image_uri),
- intval($uid)
- );
- if($r) {
- q("update attach SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s'
- WHERE id = %d AND uid = %d",
- dbesc($str_contact_allow),
- dbesc($str_group_allow),
- dbesc($str_contact_deny),
- dbesc($str_group_deny),
- intval($r[0]['id']),
- intval($uid)
- );
- }
- }
- }
- }
- }
-}
-
-
-function fix_attached_file_permissions($channel,$observer_hash,$body,
- $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny) {
-
- if(get_pconfig($channel['channel_id'],'system','force_public_uploads')) {
- $str_contact_allow = $str_group_allow = $str_contact_deny = $str_group_deny = '';
- }
-
- $match = false;
-
- if(preg_match_all("/\[attachment\](.*?)\[\/attachment\]/",$body,$match)) {
- $attaches = $match[1];
- if($attaches) {
- foreach($attaches as $attach) {
- $hash = substr($attach,0,strpos($attach,','));
- $rev = intval(substr($attach,strpos($attach,',')));
- attach_store($channel,$observer_hash,$options = 'update', array(
- 'hash' => $hash,
- 'revision' => $rev,
- 'allow_cid' => $str_contact_allow,
- 'allow_gid' => $str_group_allow,
- 'deny_cid' => $str_contact_deny,
- 'deny_gid' => $str_group_deny
- ));
- }
- }
- }
-}
-
-function item_check_service_class($channel_id,$iswebpage) {
- $ret = array('success' => false, 'message' => '');
-
- if ($iswebpage) {
- $r = q("select count(i.id) as total from item i
- right join channel c on (i.author_xchan=c.channel_hash and i.uid=c.channel_id )
- and i.parent=i.id and i.item_type = %d and i.item_deleted = 0 and i.uid= %d ",
- intval(ITEM_TYPE_WEBPAGE),
- intval($channel_id)
- );
- }
- else {
- $r = q("select count(id) as total from item where parent = id and item_wall = 1 and uid = %d " . item_normal(),
- intval($channel_id)
- );
- }
-
- if(! $r) {
- $ret['message'] = t('Unable to obtain post information from database.');
- return $ret;
- }
-
- if (!$iswebpage) {
- $max = service_class_fetch($channel_id,'total_items');
- if(! service_class_allows($channel_id,'total_items',$r[0]['total'])) {
- $result['message'] .= upgrade_message() . sprintf( t('You have reached your limit of %1$.0f top level posts.'),$max);
- return $result;
- }
- }
- else {
- $max = service_class_fetch($channel_id,'total_pages');
- if(! service_class_allows($channel_id,'total_pages',$r[0]['total'])) {
- $result['message'] .= upgrade_message() . sprintf( t('You have reached your limit of %1$.0f webpages.'),$max);
- return $result;
- }
- }
-
- $ret['success'] = true;
- return $ret;
-}
-
diff --git a/mod/lang.php b/mod/lang.php
deleted file mode 100644
index fba5f9c73..000000000
--- a/mod/lang.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-
-function lang_content(&$a) {
- return lang_selector();
-}
-
diff --git a/mod/layouts.php b/mod/layouts.php
deleted file mode 100644
index e28c9a066..000000000
--- a/mod/layouts.php
+++ /dev/null
@@ -1,193 +0,0 @@
-<?php
-
-require_once('include/identity.php');
-require_once('include/conversation.php');
-require_once('include/acl_selectors.php');
-
-function layouts_init(&$a) {
-
- 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 layouts_content(&$a) {
-
- 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'],
- 'bang' => '',
- 'showacl' => false,
- 'visitor' => false,
- 'nopreview' => 1,
- '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;
-}
diff --git a/mod/like.php b/mod/like.php
deleted file mode 100755
index 0fbdd5c30..000000000
--- a/mod/like.php
+++ /dev/null
@@ -1,541 +0,0 @@
-<?php
-
-require_once('include/security.php');
-require_once('include/bbcode.php');
-require_once('include/items.php');
-
-
-function like_content(&$a) {
-
- $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();
-}
-
-
diff --git a/mod/linkinfo.php b/mod/linkinfo.php
deleted file mode 100644
index 07eaa02a0..000000000
--- a/mod/linkinfo.php
+++ /dev/null
@@ -1,371 +0,0 @@
-<?php
-
-
-function arr_add_hashes(&$item,$k) {
- $item = '#' . $item;
-}
-
-
-
-function linkinfo_content(&$a) {
-
- 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,'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 = 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();
-
-}
-
-
-function deletexnode(&$doc, $node) {
- $xpath = new DomXPath($doc);
- $list = $xpath->query("//".$node);
- foreach ($list as $child)
- $child->parentNode->removeChild($child);
-}
-
-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);
-}
-
-
-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);
-
- deletexnode($doc, 'style');
- deletexnode($doc, 'script');
- deletexnode($doc, 'option');
- deletexnode($doc, 'h1');
- deletexnode($doc, 'h2');
- deletexnode($doc, 'h3');
- deletexnode($doc, 'h4');
- deletexnode($doc, 'h5');
- deletexnode($doc, 'h6');
- deletexnode($doc, 'ol');
- 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 = 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 = 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);
-}
diff --git a/mod/lockview.php b/mod/lockview.php
deleted file mode 100644
index d4a626a11..000000000
--- a/mod/lockview.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-
-
-function lockview_content(&$a) {
-
- $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();
-
-
-}
diff --git a/mod/locs.php b/mod/locs.php
deleted file mode 100644
index 1daf41b89..000000000
--- a/mod/locs.php
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php /** @file */
-
-
-function locs_post(&$a) {
-
- 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 locs_content(&$a) {
-
-
- 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;
-}
diff --git a/mod/login.php b/mod/login.php
deleted file mode 100644
index 31a4e7fc0..000000000
--- a/mod/login.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-
-function login_content(&$a) {
- if(local_channel())
- goaway(z_root());
- return login((App::$config['system']['register_policy'] == REGISTER_CLOSED) ? false : true);
-}
diff --git a/mod/lostpass.php b/mod/lostpass.php
deleted file mode 100644
index 2ae955983..000000000
--- a/mod/lostpass.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-
-
-function lostpass_post(&$a) {
-
- $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 lostpass_content(&$a) {
-
-
- 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;
- }
-
-}
diff --git a/mod/magic.php b/mod/magic.php
deleted file mode 100644
index 74adbfd6d..000000000
--- a/mod/magic.php
+++ /dev/null
@@ -1,167 +0,0 @@
-<?php
-
-@require_once('include/zot.php');
-
-function magic_init(&$a) {
-
- $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);
-
-}
diff --git a/mod/mail.php b/mod/mail.php
deleted file mode 100644
index 1ab2bc5ab..000000000
--- a/mod/mail.php
+++ /dev/null
@@ -1,391 +0,0 @@
-<?php
-
-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');
-
-
-function mail_post(&$a) {
-
- 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 mail_content(&$a) {
-
- $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;
-
-}
diff --git a/mod/manage.php b/mod/manage.php
deleted file mode 100644
index 5ac3e6af8..000000000
--- a/mod/manage.php
+++ /dev/null
@@ -1,175 +0,0 @@
-<?php
-
-function manage_content(&$a) {
-
- 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;
-
-}
diff --git a/mod/match.php b/mod/match.php
deleted file mode 100644
index f7fc6cebd..000000000
--- a/mod/match.php
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-
-/**
- * @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
- */
-function match_content(&$a) {
-
- $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;
-}
diff --git a/mod/menu.php b/mod/menu.php
deleted file mode 100644
index e11483c2d..000000000
--- a/mod/menu.php
+++ /dev/null
@@ -1,167 +0,0 @@
-<?php
-
-require_once('include/menu.php');
-require_once('include/identity.php');
-
-function menu_init(&$a) {
- 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 menu_post(&$a) {
-
- $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 menu_content(&$a) {
-
- $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;
- }
- }
-
-}
diff --git a/mod/message.php b/mod/message.php
deleted file mode 100644
index f6d1d020c..000000000
--- a/mod/message.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-
-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');
-
-
-function message_content(&$a) {
-
- $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;
-}
diff --git a/mod/mitem.php b/mod/mitem.php
deleted file mode 100644
index 5503e93f6..000000000
--- a/mod/mitem.php
+++ /dev/null
@@ -1,239 +0,0 @@
-<?php
-
-require_once('include/menu.php');
-require_once('include/acl_selectors.php');
-
-function mitem_init(&$a) {
-
- $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 mitem_post(&$a) {
-
- $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 mitem_content(&$a) {
-
- $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;
- }
- }
-}
diff --git a/mod/mood.php b/mod/mood.php
deleted file mode 100755
index 3ded65469..000000000
--- a/mod/mood.php
+++ /dev/null
@@ -1,140 +0,0 @@
-<?php
-
-require_once('include/security.php');
-require_once('include/bbcode.php');
-require_once('include/items.php');
-
-
-function mood_init(&$a) {
-
- 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 mood_content(&$a) {
-
- 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;
-
-}
diff --git a/mod/msearch.php b/mod/msearch.php
deleted file mode 100644
index f94b75910..000000000
--- a/mod/msearch.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-function msearch_post(&$a) {
-
- $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();
-
-} \ No newline at end of file
diff --git a/mod/network.php b/mod/network.php
deleted file mode 100644
index e6d02f572..000000000
--- a/mod/network.php
+++ /dev/null
@@ -1,525 +0,0 @@
-<?php
-
-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');
-
-
-function network_init(&$a) {
- 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 network_content(&$a, $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, (($channel['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : '')),
- '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;
-}
diff --git a/mod/new_channel.php b/mod/new_channel.php
deleted file mode 100644
index f3b63b655..000000000
--- a/mod/new_channel.php
+++ /dev/null
@@ -1,145 +0,0 @@
-<?php
-
-require_once('include/identity.php');
-require_once('include/permissions.php');
-
-
-function new_channel_init(&$a) {
-
- $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 new_channel_post(&$a) {
-
- $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 new_channel_content(&$a) {
-
- $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;
-
-}
-
diff --git a/mod/nojs.php b/mod/nojs.php
deleted file mode 100644
index c6e04a72b..000000000
--- a/mod/nojs.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-function nojs_init(&$a) {
-
- setcookie('jsdisabled', 1, 0);
- $p = $_GET['query'];
- $hasq = strpos($p,'?');
- goaway(z_root() . (($p) ? '/' . $p : '') . (($hasq) ? '' : '?f=' ) . '&jsdisabled=1');
-
-} \ No newline at end of file
diff --git a/mod/notes.php b/mod/notes.php
deleted file mode 100644
index 9bf37d0f9..000000000
--- a/mod/notes.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php /** @file */
-
-function notes_init(&$a) {
-
- 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);
-
-}
diff --git a/mod/notifications.php b/mod/notifications.php
deleted file mode 100644
index 45eb6483b..000000000
--- a/mod/notifications.php
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-
-function notifications_post(&$a) {
-
- 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 notifications_content(&$a) {
-
- 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;
-}
diff --git a/mod/notify.php b/mod/notify.php
deleted file mode 100644
index d56871880..000000000
--- a/mod/notify.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-
-
-function notify_init(&$a) {
- 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 notify_content(&$a) {
- 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;
-
-} \ No newline at end of file
diff --git a/mod/oembed.php b/mod/oembed.php
deleted file mode 100644
index a3ac8672d..000000000
--- a/mod/oembed.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-require_once("include/oembed.php");
-
-function oembed_init(&$a){
- // 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();
-}
diff --git a/mod/oep.php b/mod/oep.php
deleted file mode 100644
index 36741a752..000000000
--- a/mod/oep.php
+++ /dev/null
@@ -1,398 +0,0 @@
-<?php
-
-// oembed provider
-
-
-
-function oep_init(&$a) {
-
- 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 = oep_album_reply($_REQUEST);
- elseif(fnmatch('*/photos/*/image/*',$url))
- $arr = oep_photo_reply($_REQUEST);
- elseif(fnmatch('*/photos*',$url))
- $arr = oep_phototop_reply($_REQUEST);
- elseif(fnmatch('*/display/*',$url))
- $arr = oep_display_reply($_REQUEST);
- elseif(fnmatch('*/channel/*mid=*',$url))
- $arr = oep_mid_reply($_REQUEST);
- elseif(fnmatch('*/channel*',$url))
- $arr = oep_profile_reply($_REQUEST);
- elseif(fnmatch('*/profile/*',$url))
- $arr = 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($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;
-
-} \ No newline at end of file
diff --git a/mod/oexchange.php b/mod/oexchange.php
deleted file mode 100644
index 342b8c3cd..000000000
--- a/mod/oexchange.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-
-function oexchange_init(&$a) {
-
- 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 oexchange_content(&$a) {
-
- 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;
- require_once('mod/item.php');
- item_post($a);
-
-}
-
-
diff --git a/mod/online.php b/mod/online.php
deleted file mode 100644
index c6500347a..000000000
--- a/mod/online.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php /** @file */
-
-function online_init(&$a) {
-
- $ret = array('result' => false);
- if(argc() != 2)
- json_return_and_die($ret);
-
- $ret = get_online_status(argv(1));
- json_return_and_die($ret);
-}
diff --git a/mod/openid.php b/mod/openid.php
deleted file mode 100644
index 1ca1ba91e..000000000
--- a/mod/openid.php
+++ /dev/null
@@ -1,192 +0,0 @@
-<?php
-
-
-require_once('library/openid/openid.php');
-require_once('include/auth.php');
-
-function openid_content(&$a) {
-
- $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
-}
diff --git a/mod/opensearch.php b/mod/opensearch.php
deleted file mode 100644
index 19f7985c5..000000000
--- a/mod/opensearch.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-function opensearch_init(&$a) {
-
- $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();
-
-}
diff --git a/mod/page.php b/mod/page.php
deleted file mode 100644
index c7b827e4d..000000000
--- a/mod/page.php
+++ /dev/null
@@ -1,144 +0,0 @@
-<?php
-
-require_once('include/items.php');
-require_once('include/conversation.php');
-require_once('include/page_widgets.php');
-
-function page_init(&$a) {
- // 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 (( 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 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) {
- require_once('include/comanche.php');
- comanche_parser(get_app(),$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) {
- require_once('include/comanche.php');
- comanche_parser(get_app(),$l[0]['body']);
- App::$pdl = $l[0]['body'];
- }
- }
-
- App::$data['webpage'] = $r;
-
-}
-
-
-
-
-function page_content(&$a) {
-
- $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;
-
-}
diff --git a/mod/pconfig.php b/mod/pconfig.php
deleted file mode 100755
index 64fc1271c..000000000
--- a/mod/pconfig.php
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-
-
-function disallowed_pconfig() {
- return array(
- 'permissions_role'
- );
-}
-
-
-function pconfig_post(&$a) {
-
- 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),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 pconfig_content(&$a) {
-
- 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),disallowed_pconfig())) {
- notice( t('This setting requires special processing and editing has been blocked.') . EOL);
- return $content;
- }
- else
- $content .= 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;
-
-}
diff --git a/mod/pdledit.php b/mod/pdledit.php
deleted file mode 100644
index bf29b2da0..000000000
--- a/mod/pdledit.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-function pdledit_post(&$a) {
- 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 pdledit_content(&$a) {
-
- 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;
-}
diff --git a/mod/photo.php b/mod/photo.php
deleted file mode 100644
index 93c6efa95..000000000
--- a/mod/photo.php
+++ /dev/null
@@ -1,244 +0,0 @@
-<?php
-
-require_once('include/security.php');
-require_once('include/photo/photo_driver.php');
-
-function photo_init(&$a) {
-
- $prvcachecontrol = false;
-
- switch(argc()) {
- case 4:
- $person = argv(3);
- $res = argv(2);
- $type = argv(1);
- break;
- case 2:
- $photo = argv(1);
- break;
- case 1:
- default:
- killme();
- // NOTREACHED
- }
-
- $observer_xchan = get_observer_hash();
-
- $default = get_default_profile_photo();
-
- if(isset($type)) {
-
- /**
- * Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites.
- *
- */
-
- if($type === 'profile') {
- switch($res) {
-
- case 'm':
- $resolution = 5;
- $default = get_default_profile_photo(80);
- break;
- case 's':
- $resolution = 6;
- $default = get_default_profile_photo(48);
- break;
- case 'l':
- default:
- $resolution = 4;
- break;
- }
- }
-
- $uid = $person;
-
- $r = q("SELECT * FROM photo WHERE scale = %d AND uid = %d AND photo_usage = %d LIMIT 1",
- intval($resolution),
- intval($uid),
- intval(PHOTO_PROFILE)
- );
- if(count($r)) {
- $data = dbunescbin($r[0]['data']);
- $mimetype = $r[0]['type'];
- }
- if(intval($r[0]['os_storage']))
- $data = file_get_contents($data);
- if(! isset($data)) {
- $data = file_get_contents($default);
- $mimetype = 'image/png';
- }
- }
- else {
-
- /**
- * Other photos
- */
-
- /* Check for a cookie to indicate display pixel density, in order to detect high-resolution
- displays. This procedure was derived from the "Retina Images" by Jeremey Worboys,
- used in accordance with the Creative Commons Attribution 3.0 Unported License.
- Project link: https://github.com/Retina-Images/Retina-Images
- License link: http://creativecommons.org/licenses/by/3.0/
- */
- $cookie_value = false;
- if (isset($_COOKIE['devicePixelRatio'])) {
- $cookie_value = intval($_COOKIE['devicePixelRatio']);
- }
- else {
- // Force revalidation of cache on next request
- $cache_directive = 'no-cache';
- $status = 'no cookie';
- }
-
- $resolution = 0;
-
- if(strpos($photo,'.') !== false)
- $photo = substr($photo,0,strpos($photo,'.'));
-
- if(substr($photo,-2,1) == '-') {
- $resolution = intval(substr($photo,-1,1));
- $photo = substr($photo,0,-2);
- // If viewing on a high-res screen, attempt to serve a higher resolution image:
- if ($resolution == 2 && ($cookie_value > 1))
- {
- $resolution = 1;
- }
- }
-
- // If using resolution 1, make sure it exists before proceeding:
- if ($resolution == 1)
- {
- $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND scale = %d LIMIT 1",
- dbesc($photo),
- intval($resolution)
- );
- if (!($r))
- $resolution = 2;
- }
-
- $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND scale = %d LIMIT 1",
- dbesc($photo),
- intval($resolution)
- );
- if($r) {
-
- $allowed = (($r[0]['uid']) ? perm_is_allowed($r[0]['uid'],$observer_xchan,'view_storage') : true);
-
- $sql_extra = permissions_sql($r[0]['uid']);
-
- // Now we'll see if we can access the photo
-
- $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND scale = %d $sql_extra LIMIT 1",
- dbesc($photo),
- intval($resolution)
- );
-
- if($r && $allowed) {
- $data = dbunescbin($r[0]['data']);
- $mimetype = $r[0]['type'];
- if(intval($r[0]['os_storage']))
- $data = file_get_contents($data);
- }
- else {
-
- // Does the picture exist? It may be a remote person with no credentials,
- // but who should otherwise be able to view it. Show a default image to let
- // them know permissions was denied. It may be possible to view the image
- // through an authenticated profile visit.
- // There won't be many completely unauthorised people seeing this because
- // they won't have the photo link, so there's a reasonable chance that the person
- // might be able to obtain permission to view it.
-
- $r = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `scale` = %d LIMIT 1",
- dbesc($photo),
- intval($resolution)
- );
-
- if($r) {
- logger('mod_photo: forbidden. ' . App::$query_string);
- $observer = App::get_observer();
- logger('mod_photo: observer = ' . (($observer) ? $observer['xchan_addr'] : '(not authenticated)'));
- $data = file_get_contents('images/nosign.png');
- $mimetype = 'image/png';
- $prvcachecontrol = true;
- }
- }
- }
- }
-
- if(! isset($data)) {
- if(isset($resolution)) {
- switch($resolution) {
-
- case 4:
- $data = file_get_contents(get_default_profile_photo());
- $mimetype = 'image/png';
- break;
- case 5:
- $data = file_get_contents(get_default_profile_photo(80));
- $mimetype = 'image/png';
- break;
- case 6:
- $data = file_get_contents(get_default_profile_photo(48));
- $mimetype = 'image/png';
- break;
- default:
- killme();
- // NOTREACHED
- break;
- }
- }
- }
-
- if(isset($res) && intval($res) && $res < 500) {
- $ph = photo_factory($data, $mimetype);
- if($ph->is_valid()) {
- $ph->scaleImageSquare($res);
- $data = $ph->imageString();
- $mimetype = $ph->getType();
- }
- }
-
- // Writing in cachefile
- if (isset($cachefile) && $cachefile != '')
- file_put_contents($cachefile, $data);
-
- if(function_exists('header_remove')) {
- header_remove('Pragma');
- header_remove('pragma');
- }
-
- header("Content-type: " . $mimetype);
-
- if($prvcachecontrol) {
-
- // it is a private photo that they have no permission to view.
- // tell the browser not to cache it, in case they authenticate
- // and subsequently have permission to see it
-
- header("Cache-Control: no-store, no-cache, must-revalidate");
-
- }
- else {
- // The photo cache default is 1 day to provide a privacy trade-off,
- // as somebody reducing photo permissions on a photo that is already
- // "in the wild" won't be able to stop the photo from being viewed
- // for this amount amount of time once it is in the browser cache.
- // The privacy expectations of your site members and their perception
- // of privacy where it affects the entire project may be affected.
- // This has performance considerations but we highly recommend you
- // leave it alone.
-
- $cache = get_config('system','photo_cache_time');
- if(! $cache)
- $cache = (3600 * 24); // 1 day
-
- header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT");
- header("Cache-Control: max-age=" . $cache);
-
- }
- echo $data;
- killme();
- // NOTREACHED
-}
diff --git a/mod/photos.php b/mod/photos.php
deleted file mode 100644
index bf904db22..000000000
--- a/mod/photos.php
+++ /dev/null
@@ -1,1378 +0,0 @@
-<?php
-require_once('include/photo/photo_driver.php');
-require_once('include/photos.php');
-require_once('include/items.php');
-require_once('include/acl_selectors.php');
-require_once('include/bbcode.php');
-require_once('include/security.php');
-require_once('include/Contact.php');
-require_once('include/attach.php');
-require_once('include/text.php');
-
-
-function photos_init(&$a) {
-
-
- 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 ispublic = '" . t('everybody') . "'; var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ;
-
- }
-
- return;
-}
-
-
-
-function photos_post(&$a) {
-
- logger('mod-photos: photos_post: begin' , LOGGER_DEBUG);
-
-
- logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA);
- logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA);
-
- $ph = photo_factory('');
-
- $phototypes = $ph->supportedTypes();
-
- $can_post = false;
-
- $page_owner_uid = App::$data['channel']['channel_id'];
-
- if(perm_is_allowed($page_owner_uid,get_observer_hash(),'write_storage'))
- $can_post = true;
-
- if(! $can_post) {
- notice( t('Permission denied.') . EOL );
- if(is_ajax())
- killme();
- return;
- }
-
- $s = abook_self($page_owner_uid);
-
- if(! $s) {
- notice( t('Page owner information could not be retrieved.') . EOL);
- logger('mod_photos: post: unable to locate contact record for page owner. uid=' . $page_owner_uid);
- if(is_ajax())
- killme();
- return;
- }
-
- $owner_record = $s[0];
-
- $acl = new Zotlabs\Access\AccessList(App::$data['channel']);
-
- if((argc() > 3) && (argv(2) === 'album')) {
-
- $album = hex2bin(argv(3));
-
- if($album === t('Profile Photos')) {
- // not allowed
- goaway(z_root() . '/' . $_SESSION['photo_return']);
- }
-
- if(! photos_album_exists($page_owner_uid,$album)) {
- notice( t('Album not found.') . EOL);
- goaway(z_root() . '/' . $_SESSION['photo_return']);
- }
-
-
- /*
- * RENAME photo album
- */
-
- $newalbum = notags(trim($_REQUEST['albumname']));
- if($newalbum != $album) {
-
- // @fixme - syncronise with DAV or disallow completely
-
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
-// $x = photos_album_rename($page_owner_uid,$album,$newalbum);
-// if($x) {
-// $newurl = str_replace(bin2hex($album),bin2hex($newalbum),$_SESSION['photo_return']);
-// goaway(z_root() . '/' . $newurl);
-// }
- }
-
- /*
- * DELETE photo album and all its photos
- */
-
- if($_REQUEST['dropalbum'] == t('Delete Album')) {
-
-
- // This is dangerous because we combined file storage and photos into one interface
- // This function will remove all photos from any directory with the same name since
- // we have not passed the path value.
-
- // The correct solution would be to use a full pathname from your storage root for 'album'
- // We also need to prevent/block removing the storage root folder.
-
- $folder_hash = '';
-
- $r = q("select * from attach where is_dir = 1 and uid = %d and filename = '%s'",
- intval($page_owner_uid),
- dbesc($album)
- );
- if(! $r) {
- notice( t('Album not found.') . EOL);
- return;
- }
- if(count($r) > 1) {
- notice( t('Multiple storage folders exist with this album name, but within different directories. Please remove the desired folder or folders using the Files manager') . EOL);
- return;
- }
- else {
- $folder_hash = $r[0]['hash'];
- }
-
-
-
- $res = array();
-
- // get the list of photos we are about to delete
-
- if(remote_channel() && (! local_channel())) {
- $str = photos_album_get_db_idstr($page_owner_uid,$album,remote_channel());
- }
- elseif(local_channel()) {
- $str = photos_album_get_db_idstr(local_channel(),$album);
- }
- else {
- $str = null;
- }
- if(! $str) {
- goaway(z_root() . '/' . $_SESSION['photo_return']);
- }
-
- $r = q("select id from item where resource_id in ( $str ) and resource_type = 'photo' and uid = %d " . item_normal(),
- intval($page_owner_uid)
- );
- if($r) {
- foreach($r as $i) {
- attach_delete($page_owner_uid, $i['resource_id'], 1 );
- }
- }
-
- // remove the associated photos in case they weren't attached to an item
-
- q("delete from photo where resource_id in ( $str ) and uid = %d",
- intval($page_owner_uid)
- );
-
- // @FIXME do the same for the linked attach
-
- if($folder_hash) {
- attach_delete($page_owner_uid,$folder_hash, 1);
-
- $sync = attach_export_data(App::$data['channel'],$folder_hash, true);
-
- if($sync)
- build_sync_packet($page_owner_uid,array('file' => array($sync)));
- }
-
- }
-
- goaway(z_root() . '/photos/' . App::$data['channel']['channel_address']);
- }
-
- if((argc() > 2) && (x($_REQUEST,'delete')) && ($_REQUEST['delete'] === t('Delete Photo'))) {
-
- // same as above but remove single photo
-
- $ob_hash = get_observer_hash();
- if(! $ob_hash)
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
- $r = q("SELECT `id`, `resource_id` FROM `photo` WHERE ( xchan = '%s' or `uid` = %d ) AND `resource_id` = '%s' LIMIT 1",
- dbesc($ob_hash),
- intval(local_channel()),
- dbesc(App::$argv[2])
- );
-
- if($r) {
- attach_delete($page_owner_uid, $r[0]['resource_id'], 1 );
- $sync = attach_export_data(App::$data['channel'],$r[0]['resource_id'], true);
-
- if($sync)
- build_sync_packet($page_owner_uid,array('file' => array($sync)));
- }
-
- goaway(z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/album/' . $_SESSION['album_return']);
- }
-
-
- if((App::$argc > 2) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false)) || (x($_POST,'albname') !== false)) {
-
-
- $desc = ((x($_POST,'desc')) ? notags(trim($_POST['desc'])) : '');
- $rawtags = ((x($_POST,'newtag')) ? notags(trim($_POST['newtag'])) : '');
- $item_id = ((x($_POST,'item_id')) ? intval($_POST['item_id']) : 0);
- $albname = ((x($_POST,'albname')) ? notags(trim($_POST['albname'])) : '');
- $is_nsfw = ((x($_POST,'adult')) ? intval($_POST['adult']) : 0);
-
- $acl->set_from_array($_POST);
- $perm = $acl->get();
-
- $resource_id = argv(2);
-
- if(! strlen($albname))
- $albname = datetime_convert('UTC',date_default_timezone_get(),'now', 'Y');
-
-
- if((x($_POST,'rotate') !== false) &&
- ( (intval($_POST['rotate']) == 1) || (intval($_POST['rotate']) == 2) )) {
- logger('rotate');
-
- $r = q("select * from photo where `resource_id` = '%s' and uid = %d and scale = 0 limit 1",
- dbesc($resource_id),
- intval($page_owner_uid)
- );
- if(count($r)) {
- $d = (($r[0]['os_storage']) ? @file_get_contents($r[0]['data']) : dbunescbin($r[0]['data']));
- $ph = photo_factory($d, $r[0]['type']);
- if($ph->is_valid()) {
- $rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 );
- $ph->rotate($rotate_deg);
-
- $width = $ph->getWidth();
- $height = $ph->getHeight();
-
- if(intval($r[0]['os_storage'])) {
- @file_put_contents($r[0]['data'],$ph->imageString());
- $data = $r[0]['data'];
- $fsize = @filesize($r[0]['data']);
- q("update attach set filesize = %d where hash = '%s' and uid = %d limit 1",
- intval($fsize),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
- }
- else {
- $data = $ph->imageString();
- $fsize = strlen($data);
- }
-
- $x = q("update photo set data = '%s', `size` = %d, height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 0",
- dbescbin($data),
- intval($fsize),
- intval($height),
- intval($width),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
-
- if($width > 1024 || $height > 1024)
- $ph->scaleImage(1024);
-
- $width = $ph->getWidth();
- $height = $ph->getHeight();
-
- $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 1",
- dbescbin($ph->imageString()),
- intval($height),
- intval($width),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
-
-
- if($width > 640 || $height > 640)
- $ph->scaleImage(640);
-
- $width = $ph->getWidth();
- $height = $ph->getHeight();
-
- $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 2",
- dbescbin($ph->imageString()),
- intval($height),
- intval($width),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
-
-
- if($width > 320 || $height > 320)
- $ph->scaleImage(320);
-
- $width = $ph->getWidth();
- $height = $ph->getHeight();
-
- $x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 3",
- dbescbin($ph->imageString()),
- intval($height),
- intval($width),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
- }
- }
- }
-
- $p = q("SELECT type, is_nsfw, description, resource_id, scale, allow_cid, allow_gid, deny_cid, deny_gid FROM photo WHERE resource_id = '%s' AND uid = %d ORDER BY scale DESC",
- dbesc($resource_id),
- intval($page_owner_uid)
- );
- if($p) {
- $ext = $phototypes[$p[0]['type']];
-
- $r = q("UPDATE `photo` SET `description` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource_id` = '%s' AND `uid` = %d",
- dbesc($desc),
- dbesc($perm['allow_cid']),
- dbesc($perm['allow_gid']),
- dbesc($perm['deny_cid']),
- dbesc($perm['deny_gid']),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
- }
-
- $item_private = (($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny) ? true : false);
-
- $old_is_nsfw = $p[0]['is_nsfw'];
- if($old_is_nsfw != $is_nsfw) {
- $r = q("update photo set is_nsfw = %d where resource_id = '%s' and uid = %d",
- intval($is_nsfw),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
- }
-
- /* Don't make the item visible if the only change was the album name */
-
- $visibility = 0;
- if($p[0]['description'] !== $desc || strlen($rawtags))
- $visibility = 1;
-
- if(! $item_id) {
- $item_id = photos_create_item(App::$data['channel'],get_observer_hash(),$p[0],$visibility);
-
- }
-
- if($item_id) {
- $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval($item_id),
- intval($page_owner_uid)
- );
-
- if($r) {
- $old_tag = $r[0]['tag'];
- $old_inform = $r[0]['inform'];
- }
- }
-
-
- // make sure the linked item has the same permissions as the photo regardless of any other changes
- $x = q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d
- where id = %d",
- dbesc($perm['allow_cid']),
- dbesc($perm['allow_gid']),
- dbesc($perm['deny_cid']),
- dbesc($perm['deny_gid']),
- intval($acl->is_private()),
- intval($item_id)
- );
-
- // make sure the attach has the same permissions as the photo regardless of any other changes
- $x = q("update attach set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where hash = '%s' and uid = %d and is_photo = 1",
- dbesc($perm['allow_cid']),
- dbesc($perm['allow_gid']),
- dbesc($perm['deny_cid']),
- dbesc($perm['deny_gid']),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
-
-
-
- if(strlen($rawtags)) {
-
- $str_tags = '';
- $inform = '';
-
- // if the new tag doesn't have a namespace specifier (@foo or #foo) give it a mention
-
- $x = substr($rawtags,0,1);
- if($x !== '@' && $x !== '#')
- $rawtags = '@' . $rawtags;
-
- require_once('include/text.php');
- $profile_uid = App::$profile['profile_uid'];
-
- $results = linkify_tags($a, $rawtags, (local_channel()) ? local_channel() : $profile_uid);
-
- $success = $results['success'];
- $post_tags = array();
-
- foreach($results as $result) {
- $success = $result['success'];
- if($success['replaced']) {
- $post_tags[] = array(
- 'uid' => $profile_uid,
- 'type' => $success['termtype'],
- 'otype' => TERM_OBJ_POST,
- 'term' => $success['term'],
- 'url' => $success['url']
- );
- }
- }
-
- $r = q("select * from item where id = %d and uid = %d limit 1",
- intval($item_id),
- intval($page_owner_uid)
- );
-
- if($r) {
- $r = fetch_post_tags($r,true);
- $datarray = $r[0];
- if($post_tags) {
- if((! array_key_exists('term',$datarray)) || (! is_array($datarray['term'])))
- $datarray['term'] = $post_tags;
- else
- $datarray['term'] = array_merge($datarray['term'],$post_tags);
- }
- item_store_update($datarray,$execflag);
- }
-
- }
-
- goaway(z_root() . '/' . $_SESSION['photo_return']);
- return; // NOTREACHED
-
- $sync = attach_export_data(App::$data['channel'],$resource_id);
-
- if($sync)
- build_sync_packet($page_owner_uid,array('file' => array($sync)));
-
- }
-
-
- /**
- * default post action - upload a photo
- */
-
- $channel = App::$data['channel'];
- $observer = App::$data['observer'];
-
- $_REQUEST['source'] = 'photos';
- require_once('include/attach.php');
-
- if(! local_channel()) {
- $_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']);
- $_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']);
- $_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']);
- $_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']);
- }
-
- $r = attach_store($channel,get_observer_hash(), '', $_REQUEST);
-
- if(! $r['success']) {
- notice($r['message'] . EOL);
- }
-
- if($_REQUEST['newalbum'])
- goaway(z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/album/' . bin2hex($_REQUEST['newalbum']));
- else
- goaway(z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/album/' . bin2hex(datetime_convert('UTC',date_default_timezone_get(),'now', 'Y')));
-
-}
-
-
-
-function photos_content(&$a) {
-
- // URLs:
- // photos/name
- // photos/name/album/xxxxx (xxxxx is album name)
- // photos/name/image/xxxxx
-
-
- if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
- notice( t('Public access denied.') . EOL);
- return;
- }
-
- $unsafe = ((array_key_exists('unsafe',$_REQUEST) && $_REQUEST['unsafe']) ? 1 : 0);
-
- require_once('include/bbcode.php');
- require_once('include/security.php');
- require_once('include/conversation.php');
-
- if(! x(App::$data,'channel')) {
- notice( t('No photos selected') . EOL );
- return;
- }
-
- $ph = photo_factory('');
- $phototypes = $ph->supportedTypes();
-
- $_SESSION['photo_return'] = App::$cmd;
-
- //
- // Parse arguments
- //
-
- $can_comment = perm_is_allowed(App::$profile['profile_uid'],get_observer_hash(),'post_comments');
-
- if(argc() > 3) {
- $datatype = argv(2);
- $datum = argv(3);
- } else {
- if(argc() > 2) {
- $datatype = argv(2);
- $datum = '';
- }
- else
- $datatype = 'summary';
- }
-
- if(argc() > 4)
- $cmd = argv(4);
- else
- $cmd = 'view';
-
- //
- // Setup permissions structures
- //
-
- $can_post = false;
- $visitor = 0;
-
-
- $owner_uid = App::$data['channel']['channel_id'];
- $owner_aid = App::$data['channel']['channel_account_id'];
-
- $observer = App::get_observer();
-
- $can_post = perm_is_allowed($owner_uid,$observer['xchan_hash'],'write_storage');
- $can_view = perm_is_allowed($owner_uid,$observer['xchan_hash'],'view_storage');
-
- if(! $can_view) {
- notice( t('Access to this item is restricted.') . EOL);
- return;
- }
-
- $sql_extra = permissions_sql($owner_uid);
-
- $o = "";
-
- $o .= "<script> var profile_uid = " . App::$profile['profile_uid']
- . "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
-
- // tabs
-
- $_is_owner = (local_channel() && (local_channel() == $owner_uid));
- $o .= profile_tabs($a,$_is_owner, App::$data['channel']['channel_address']);
-
- /**
- * Display upload form
- */
-
- if( $can_post) {
-
- $uploader = '';
-
- $ret = array('post_url' => z_root() . '/photos/' . App::$data['channel']['channel_address'],
- 'addon_text' => $uploader,
- 'default_upload' => true);
-
- call_hooks('photo_upload_form',$ret);
-
- /* Show space usage */
-
- $r = q("select sum(size) as total from photo where aid = %d and scale = 0 ",
- intval(App::$data['channel']['channel_account_id'])
- );
-
-
- $limit = service_class_fetch(App::$data['channel']['channel_id'],'photo_upload_limit');
- if($limit !== false) {
- $usage_message = sprintf( t("%1$.2f MB of %2$.2f MB photo storage used."), $r[0]['total'] / 1024000, $limit / 1024000 );
- }
- else {
- $usage_message = sprintf( t('%1$.2f MB photo storage used.'), $r[0]['total'] / 1024000 );
- }
-
- if($_is_owner) {
- $channel = App::get_channel();
-
- $acl = new Zotlabs\Access\AccessList($channel);
- $channel_acl = $acl->get();
-
- $lockstate = (($acl->is_private()) ? 'lock' : 'unlock');
- }
-
- $aclselect = (($_is_owner) ? populate_acl($channel_acl,false) : '');
-
- // this is wrong but is to work around an issue with js_upload wherein it chokes if these variables
- // don't exist. They really should be set to a parseable representation of the channel's default permissions
- // which can be processed by getSelected()
-
- if(! $aclselect) {
- $aclselect = '<input id="group_allow" type="hidden" name="allow_gid[]" value="" /><input id="contact_allow" type="hidden" name="allow_cid[]" value="" /><input id="group_deny" type="hidden" name="deny_gid[]" value="" /><input id="contact_deny" type="hidden" name="deny_cid[]" value="" />';
- }
-
- $selname = (($datum) ? hex2bin($datum) : '');
-
- $albums = ((array_key_exists('albums', App::$data)) ? App::$data['albums'] : photos_albums_list(App::$data['channel'],App::$data['observer']));
-
- if(! $selname) {
- $def_album = get_pconfig(App::$data['channel']['channel_id'],'system','photo_path');
- if($def_album) {
- $selname = filepath_macro($def_album);
- $albums['album'][] = array('text' => $selname);
- }
- }
-
- $tpl = get_markup_template('photos_upload.tpl');
- $upload_form = replace_macros($tpl,array(
- '$pagename' => t('Upload Photos'),
- '$sessid' => session_id(),
- '$usage' => $usage_message,
- '$nickname' => App::$data['channel']['channel_address'],
- '$newalbum_label' => t('Enter an album name'),
- '$newalbum_placeholder' => t('or select an existing album (doubleclick)'),
- '$visible' => array('visible', t('Create a status post for this upload'), 0,'', array(t('No'), t('Yes')), 'onclick="showHideBodyTextarea();"'),
- '$caption' => array('description', t('Caption (optional):')),
- '$body' => array('body', t('Description (optional):'),'', 'Description will only appear in the status post'),
- '$albums' => $albums['albums'],
- '$selname' => $selname,
- '$permissions' => t('Permissions'),
- '$aclselect' => $aclselect,
- '$lockstate' => $lockstate,
- '$uploader' => $ret['addon_text'],
- '$default' => (($ret['default_upload']) ? true : false),
- '$uploadurl' => $ret['post_url'],
- '$submit' => t('Submit')
-
- ));
-
- }
-
- //
- // dispatch request
- //
-
- /*
- * Display a single photo album
- */
-
- if($datatype === 'album') {
-
- if(strlen($datum)) {
- if((strlen($datum) & 1) || (! ctype_xdigit($datum))) {
- notice( t('Album name could not be decoded') . EOL);
- logger('mod_photos: illegal album encoding: ' . $datum);
- $datum = '';
- }
- }
-
- $album = (($datum) ? hex2bin($datum) : '');
-
-
- App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$cmd) . '" title="oembed" />' . "\r\n";
-
-
- $r = q("SELECT `resource_id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` = '%s'
- AND `scale` <= 4 and photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY `resource_id`",
- intval($owner_uid),
- dbesc($album),
- intval(PHOTO_NORMAL),
- intval(PHOTO_PROFILE),
- intval($unsafe)
- );
- if(count($r)) {
- App::set_pager_total(count($r));
- App::set_pager_itemspage(60);
- } else {
- goaway(z_root() . '/photos/' . App::$data['channel']['channel_address']);
- }
-
- if($_GET['order'] === 'posted')
- $order = 'ASC';
- else
- $order = 'DESC';
-
-
- $r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.scale, p.description, p.created FROM photo p INNER JOIN
- (SELECT resource_id, max(scale) scale FROM photo WHERE uid = %d AND album = '%s' AND scale <= 4 AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id) ph
- ON (p.resource_id = ph.resource_id AND p.scale = ph.scale)
- ORDER BY created $order LIMIT %d OFFSET %d",
- intval($owner_uid),
- dbesc($album),
- intval(PHOTO_NORMAL),
- intval(PHOTO_PROFILE),
- intval($unsafe),
- intval(App::$pager['itemspage']),
- intval(App::$pager['start'])
- );
-
- //edit album name
- $album_edit = null;
- if(($album !== t('Profile Photos')) && ($album !== 'Profile Photos') && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) {
- if($can_post) {
- $album_e = $album;
- $albums = ((array_key_exists('albums', App::$data)) ? App::$data['albums'] : photos_albums_list(App::$data['channel'],App::$data['observer']));
-
- // @fixme - syncronise actions with DAV
-
-// $edit_tpl = get_markup_template('album_edit.tpl');
-// $album_edit = replace_macros($edit_tpl,array(
-// '$nametext' => t('Enter a new album name'),
-// '$name_placeholder' => t('or select an existing one (doubleclick)'),
-// '$nickname' => App::$data['channel']['channel_address'],
-// '$album' => $album_e,
-// '$albums' => $albums['albums'],
-// '$hexalbum' => bin2hex($album),
-// '$submit' => t('Submit'),
-// '$dropsubmit' => t('Delete Album')
-// ));
-
- }
- }
-
- if($_GET['order'] === 'posted')
- $order = array(t('Show Newest First'), z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/album/' . bin2hex($album));
- else
- $order = array(t('Show Oldest First'), z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/album/' . bin2hex($album) . '?f=&order=posted');
-
- $photos = array();
- if(count($r)) {
- $twist = 'rotright';
- foreach($r as $rr) {
-
- if($twist == 'rotright')
- $twist = 'rotleft';
- else
- $twist = 'rotright';
-
- $ext = $phototypes[$rr['type']];
-
- $imgalt_e = $rr['filename'];
- $desc_e = $rr['description'];
-
- $imagelink = (z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id']
- . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''));
-
- $photos[] = array(
- 'id' => $rr['id'],
- 'twist' => ' ' . $twist . rand(2,4),
- 'link' => $imagelink,
- 'title' => t('View Photo'),
- 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['scale'] . '.' .$ext,
- 'alt' => $imgalt_e,
- 'desc'=> $desc_e,
- 'ext' => $ext,
- 'hash'=> $rr['resource_id'],
- 'unknown' => t('Unknown')
- );
- }
- }
-
- if($_REQUEST['aj']) {
- if($photos) {
- $o = replace_macros(get_markup_template('photosajax.tpl'),array(
- '$photos' => $photos,
- '$album_id' => bin2hex($album)
- ));
- }
- 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>";
- $tpl = get_markup_template('photo_album.tpl');
- $o .= replace_macros($tpl, array(
- '$photos' => $photos,
- '$album' => $album,
- '$album_id' => bin2hex($album),
- '$album_edit' => array(t('Edit Album'), $album_edit),
- '$can_post' => $can_post,
- '$upload' => array(t('Upload'), z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/upload/' . bin2hex($album)),
- '$order' => $order,
- '$upload_form' => $upload_form,
- '$usage' => $usage_message
- ));
-
- }
-
- if((! $photos) && ($_REQUEST['aj'])) {
- $o .= '<div id="content-complete"></div>';
- echo $o;
- killme();
- }
-
-// $o .= paginate($a);
-
- return $o;
-
- }
-
- /**
- * Display one photo
- */
-
- if($datatype === 'image') {
-
- App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$cmd) . '" title="oembed" />' . "\r\n";
-
- // fetch image, item containing image, then comments
-
- $ph = q("SELECT id,aid,uid,xchan,resource_id,created,edited,title,`description`,album,filename,`type`,height,width,`size`,scale,photo_usage,is_nsfw,allow_cid,allow_gid,deny_cid,deny_gid FROM `photo` WHERE `uid` = %d AND `resource_id` = '%s'
- $sql_extra ORDER BY `scale` ASC ",
- intval($owner_uid),
- dbesc($datum)
- );
-
- if(! $ph) {
-
- /* Check again - this time without specifying permissions */
-
- $ph = q("SELECT id FROM photo WHERE uid = %d AND resource_id = '%s' LIMIT 1",
- intval($owner_uid),
- dbesc($datum)
- );
- if($ph)
- notice( t('Permission denied. Access to this item may be restricted.') . EOL);
- else
- notice( t('Photo not available') . EOL );
- return;
- }
-
-
-
- $prevlink = '';
- $nextlink = '';
-
- if($_GET['order'] === 'posted')
- $order = 'ASC';
- else
- $order = 'DESC';
-
-
- $prvnxt = q("SELECT `resource_id` FROM `photo` WHERE `album` = '%s' AND `uid` = %d AND `scale` = 0
- $sql_extra ORDER BY `created` $order ",
- dbesc($ph[0]['album']),
- intval($owner_uid)
- );
-
- if(count($prvnxt)) {
- for($z = 0; $z < count($prvnxt); $z++) {
- if($prvnxt[$z]['resource_id'] == $ph[0]['resource_id']) {
- $prv = $z - 1;
- $nxt = $z + 1;
- if($prv < 0)
- $prv = count($prvnxt) - 1;
- if($nxt >= count($prvnxt))
- $nxt = 0;
- break;
- }
- }
-
- $prevlink = z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
- $nextlink = z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
- }
-
-
- if(count($ph) == 1)
- $hires = $lores = $ph[0];
- if(count($ph) > 1) {
- if($ph[1]['scale'] == 2) {
- // original is 640 or less, we can display it directly
- $hires = $lores = $ph[0];
- }
- else {
- $hires = $ph[0];
- $lores = $ph[1];
- }
- }
-
- $album_link = z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/album/' . bin2hex($ph[0]['album']);
- $tools = Null;
- $lock = Null;
-
- if($can_post && ($ph[0]['uid'] == $owner_uid)) {
- $tools = array(
- 'profile'=>array(z_root() . '/profile_photo/use/'.$ph[0]['resource_id'], t('Use as profile photo')),
- 'cover'=>array(z_root() . '/cover_photo/use/'.$ph[0]['resource_id'], t('Use as cover photo')),
- );
- }
-
- // lockstate
- $lockstate = ( ( (strlen($ph[0]['allow_cid']) || strlen($ph[0]['allow_gid'])
- || strlen($ph[0]['deny_cid']) || strlen($ph[0]['deny_gid'])) )
- ? array('lock', t('Private Photo'))
- : array('unlock', Null));
-
- App::$page['htmlhead'] .= '<script>$(document).keydown(function(event) {' . "\n";
- if($prevlink)
- App::$page['htmlhead'] .= 'if(event.ctrlKey && event.keyCode == 37) { event.preventDefault(); window.location.href = \'' . $prevlink . '\'; }' . "\n";
- if($nextlink)
- App::$page['htmlhead'] .= 'if(event.ctrlKey && event.keyCode == 39) { event.preventDefault(); window.location.href = \'' . $nextlink . '\'; }' . "\n";
- App::$page['htmlhead'] .= '});</script>';
-
- if($prevlink)
- $prevlink = array($prevlink, t('Previous'));
-
- $photo = array(
- 'href' => z_root() . '/photo/' . $hires['resource_id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']],
- 'title'=> t('View Full Size'),
- 'src' => z_root() . '/photo/' . $lores['resource_id'] . '-' . $lores['scale'] . '.' . $phototypes[$lores['type']] . '?f=&_u=' . datetime_convert('','','','ymdhis')
- );
-
- if($nextlink)
- $nextlink = array($nextlink, t('Next'));
-
-
- // Do we have an item for this photo?
-
- $linked_items = q("SELECT * FROM item WHERE resource_id = '%s' and resource_type = 'photo'
- $sql_extra LIMIT 1",
- dbesc($datum)
- );
-
- $map = null;
-
- if($linked_items) {
-
- xchan_query($linked_items);
- $linked_items = fetch_post_tags($linked_items,true);
-
- $link_item = $linked_items[0];
- $item_normal = item_normal();
-
- $r = q("select * from item where parent_mid = '%s'
- $item_normal and uid = %d $sql_extra ",
- dbesc($link_item['mid']),
- intval($link_item['uid'])
-
- );
-
- if($r) {
- xchan_query($r);
- $r = fetch_post_tags($r,true);
- $r = conv_sort($r,'commented');
- }
-
- $tags = array();
- if($link_item['term']) {
- $cnt = 0;
- foreach($link_item['term'] as $t) {
- $tags[$cnt] = array(0 => format_term_for_display($t));
- if($can_post && ($ph[0]['uid'] == $owner_uid)) {
- $tags[$cnt][1] = 'tagrm/drop/' . $link_item['id'] . '/' . bin2hex($t['term']); //?f=&item=' . $link_item['id'];
- $tags[$cnt][2] = t('Remove');
- }
- $cnt ++;
- }
- }
-
- if((local_channel()) && (local_channel() == $link_item['uid'])) {
- q("UPDATE `item` SET item_unseen = 0 WHERE parent = %d and uid = %d and item_unseen = 1",
- intval($link_item['parent']),
- intval(local_channel())
- );
- }
-
- if($link_item['coord']) {
- $map = generate_map($link_item['coord']);
- }
- }
-
-// logger('mod_photo: link_item' . print_r($link_item,true));
-
- // FIXME - remove this when we move to conversation module
-
- $r = $r[0]['children'];
-
- $edit = null;
- if($can_post) {
- $album_e = $ph[0]['album'];
- $caption_e = $ph[0]['description'];
- $aclselect_e = (($_is_owner) ? populate_acl($ph[0]) : '');
- $albums = ((array_key_exists('albums', App::$data)) ? App::$data['albums'] : photos_albums_list(App::$data['channel'],App::$data['observer']));
-
- $_SESSION['album_return'] = bin2hex($ph[0]['album']);
-
- $edit = array(
- 'edit' => t('Edit photo'),
- 'id' => $link_item['id'],
- 'rotatecw' => t('Rotate CW (right)'),
- 'rotateccw' => t('Rotate CCW (left)'),
- 'albums' => $albums['albums'],
- 'album' => $album_e,
- 'newalbum_label' => t('Enter a new album name'),
- 'newalbum_placeholder' => t('or select an existing one (doubleclick)'),
- 'nickname' => App::$data['channel']['channel_address'],
- 'resource_id' => $ph[0]['resource_id'],
- 'capt_label' => t('Caption'),
- 'caption' => $caption_e,
- 'tag_label' => t('Add a Tag'),
- 'permissions' => t('Permissions'),
- 'aclselect' => $aclselect_e,
- 'lockstate' => $lockstate[0],
- 'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'),
- 'item_id' => ((count($linked_items)) ? $link_item['id'] : 0),
- 'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'),
- 'adult' => array('adult',t('Flag as adult in album view'), intval($ph[0]['is_nsfw']),''),
- 'submit' => t('Submit'),
- 'delete' => t('Delete Photo')
- );
- }
-
- if(count($linked_items)) {
-
- $cmnt_tpl = get_markup_template('comment_item.tpl');
- $tpl = get_markup_template('photo_item.tpl');
- $return_url = App::$cmd;
-
- $like_tpl = get_markup_template('like_noshare.tpl');
-
- $likebuttons = '';
-
- if($can_post || $can_comment) {
- $likebuttons = array(
- 'id' => $link_item['id'],
- 'likethis' => t("I like this \x28toggle\x29"),
- 'nolike' => t("I don't like this \x28toggle\x29"),
- 'share' => t('Share'),
- 'wait' => t('Please wait')
- );
- }
-
- $comments = '';
- if(! count($r)) {
- if($can_post || $can_comment) {
- $commentbox = replace_macros($cmnt_tpl,array(
- '$return_path' => '',
- '$mode' => 'photos',
- '$jsreload' => $return_url,
- '$type' => 'wall-comment',
- '$id' => $link_item['id'],
- '$parent' => $link_item['id'],
- '$profile_uid' => $owner_uid,
- '$mylink' => $observer['xchan_url'],
- '$mytitle' => t('This is you'),
- '$myphoto' => $observer['xchan_photo_s'],
- '$comment' => t('Comment'),
- '$submit' => t('Submit'),
- '$preview' => t('Preview'),
- '$ww' => '',
- '$feature_encrypt' => false
- ));
- }
- }
-
- $alike = array();
- $dlike = array();
-
- $like = '';
- $dislike = '';
-
- $conv_responses = array(
- 'like' => array('title' => t('Likes','title')),'dislike' => array('title' => t('Dislikes','title')),
- 'agree' => array('title' => t('Agree','title')),'disagree' => array('title' => t('Disagree','title')), 'abstain' => array('title' => t('Abstain','title')),
- 'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title'))
- );
-
-
-
-
- if($r) {
-
- foreach($r as $item) {
- builtin_activity_puller($item, $conv_responses);
- }
-
-
- $like_count = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid']] : '');
- $like_list = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid'] . '-l'] : '');
- if (count($like_list) > MAX_LIKERS) {
- $like_list_part = array_slice($like_list, 0, MAX_LIKERS);
- array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
- } else {
- $like_list_part = '';
- }
- $like_button_label = tt('Like','Likes',$like_count,'noun');
-
- //if (feature_enabled($conv->get_profile_owner(),'dislike')) {
- $dislike_count = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid']] : '');
- $dislike_list = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid'] . '-l'] : '');
- $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
- if (count($dislike_list) > MAX_LIKERS) {
- $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
- array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
- } else {
- $dislike_list_part = '';
- }
- //}
-
-
- $like = ((isset($alike[$link_item['mid']])) ? format_like($alike[$link_item['mid']],$alike[$link_item['mid'] . '-l'],'like',$link_item['mid']) : '');
- $dislike = ((isset($dlike[$link_item['mid']])) ? format_like($dlike[$link_item['mid']],$dlike[$link_item['mid'] . '-l'],'dislike',$link_item['mid']) : '');
-
- // display comments
-
- foreach($r as $item) {
- $comment = '';
- $template = $tpl;
- $sparkle = '';
-
- if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent']))
- continue;
-
- $redirect_url = z_root() . '/redir/' . $item['cid'] ;
-
-
- $profile_url = zid($item['author']['xchan_url']);
- $sparkle = '';
-
-
- $profile_name = $item['author']['xchan_name'];
- $profile_avatar = $item['author']['xchan_photo_m'];
-
- $profile_link = $profile_url;
-
- $drop = '';
-
- if($observer['xchan_hash'] === $item['author_xchan'] || $observer['xchan_hash'] === $item['owner_xchan'])
- $drop = replace_macros(get_markup_template('photo_drop.tpl'), array('$id' => $item['id'], '$delete' => t('Delete')));
-
-
- $name_e = $profile_name;
- $title_e = $item['title'];
- unobscure($item);
- $body_e = prepare_text($item['body'],$item['mimetype']);
-
- $comments .= replace_macros($template,array(
- '$id' => $item['id'],
- '$mode' => 'photos',
- '$profile_url' => $profile_link,
- '$name' => $name_e,
- '$thumb' => $profile_avatar,
- '$sparkle' => $sparkle,
- '$title' => $title_e,
- '$body' => $body_e,
- '$ago' => relative_date($item['created']),
- '$indent' => (($item['parent'] != $item['id']) ? ' comment' : ''),
- '$drop' => $drop,
- '$comment' => $comment
- ));
-
- }
-
- if($can_post || $can_comment) {
- $commentbox = replace_macros($cmnt_tpl,array(
- '$return_path' => '',
- '$jsreload' => $return_url,
- '$type' => 'wall-comment',
- '$id' => $link_item['id'],
- '$parent' => $link_item['id'],
- '$profile_uid' => $owner_uid,
- '$mylink' => $observer['xchan_url'],
- '$mytitle' => t('This is you'),
- '$myphoto' => $observer['xchan_photo_s'],
- '$comment' => t('Comment'),
- '$submit' => t('Submit'),
- '$ww' => ''
- ));
- }
-
- }
- $paginate = paginate($a);
- }
-
- $album_e = array($album_link,$ph[0]['album']);
- $like_e = $like;
- $dislike_e = $dislike;
-
-
- $response_verbs = array('like');
- if(feature_enabled($owner_uid,'dislike'))
- $response_verbs[] = 'dislike';
-
-
- $responses = get_responses($conv_responses,$response_verbs,'',$link_item);
-
- $photo_tpl = get_markup_template('photo_view.tpl');
- $o .= replace_macros($photo_tpl, array(
- '$id' => $ph[0]['id'],
- '$album' => $album_e,
- '$tools' => $tools,
- '$lock' => $lockstate[1],
- '$photo' => $photo,
- '$prevlink' => $prevlink,
- '$nextlink' => $nextlink,
- '$desc' => $ph[0]['description'],
- '$filename' => $ph[0]['filename'],
- '$unknown' => t('Unknown'),
- '$tag_hdr' => t('In This Photo:'),
- '$tags' => $tags,
- 'responses' => $responses,
- '$edit' => $edit,
- '$map' => $map,
- '$map_text' => t('Map'),
- '$likebuttons' => $likebuttons,
- '$like' => $like_e,
- '$dislike' => $dislike_e,
- '$like_count' => $like_count,
- '$like_list' => $like_list,
- '$like_list_part' => $like_list_part,
- '$like_button_label' => $like_button_label,
- '$like_modal_title' => t('Likes','noun'),
- '$dislike_modal_title' => t('Dislikes','noun'),
- '$dislike_count' => $dislike_count, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
- '$dislike_list' => $dislike_list, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
- '$dislike_list_part' => $dislike_list_part, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
- '$dislike_button_label' => $dislike_button_label, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
- '$modal_dismiss' => t('Close'),
- '$comments' => $comments,
- '$commentbox' => $commentbox,
- '$paginate' => $paginate,
- ));
-
- App::$data['photo_html'] = $o;
-
- return $o;
- }
-
- // Default - show recent photos with upload link (if applicable)
- //$o = '';
-
- App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$cmd) . '" title="oembed" />' . "\r\n";
-
-
- $r = q("SELECT `resource_id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s'
- and photo_usage in ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY `resource_id`",
- intval(App::$data['channel']['channel_id']),
- dbesc('Contact Photos'),
- dbesc( t('Contact Photos')),
- intval(PHOTO_NORMAL),
- intval(PHOTO_PROFILE),
- intval($unsafe)
- );
- if(count($r)) {
- App::set_pager_total(count($r));
- App::set_pager_itemspage(60);
- }
-
- $r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.album, p.scale, p.created FROM photo p INNER JOIN
- (SELECT resource_id, max(scale) scale FROM photo
- WHERE uid=%d AND album != '%s' AND album != '%s'
- AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra group by resource_id) ph
- ON (p.resource_id = ph.resource_id and p.scale = ph.scale) ORDER by p.created DESC LIMIT %d OFFSET %d",
- intval(App::$data['channel']['channel_id']),
- dbesc('Contact Photos'),
- dbesc( t('Contact Photos')),
- intval(PHOTO_NORMAL),
- intval(PHOTO_PROFILE),
- intval($unsafe),
- intval(App::$pager['itemspage']),
- intval(App::$pager['start'])
- );
-
-
-
- $photos = array();
- if(count($r)) {
- $twist = 'rotright';
- foreach($r as $rr) {
- if($twist == 'rotright')
- $twist = 'rotleft';
- else
- $twist = 'rotright';
- $ext = $phototypes[$rr['type']];
-
- if(App::get_template_engine() === 'internal') {
- $alt_e = template_escape($rr['filename']);
- $name_e = template_escape($rr['album']);
- }
- else {
- $alt_e = $rr['filename'];
- $name_e = $rr['album'];
- }
-
- $photos[] = array(
- 'id' => $rr['id'],
- 'twist' => ' ' . $twist . rand(2,4),
- 'link' => z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id'],
- 'title' => t('View Photo'),
- 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . ((($rr['scale']) == 6) ? 4 : $rr['scale']) . '.' . $ext,
- 'alt' => $alt_e,
- 'album' => array(
- 'link' => z_root() . '/photos/' . App::$data['channel']['channel_address'] . '/album/' . bin2hex($rr['album']),
- 'name' => $name_e,
- 'alt' => t('View Album'),
- ),
-
- );
- }
- }
-
- if($_REQUEST['aj']) {
- if($photos) {
- $o = replace_macros(get_markup_template('photosajax.tpl'),array(
- '$photos' => $photos,
- '$album_id' => bin2hex(t('Recent Photos'))
- ));
- }
- 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>";
- $tpl = get_markup_template('photos_recent.tpl');
- $o .= replace_macros($tpl, array(
- '$title' => t('Recent Photos'),
- '$album_id' => bin2hex(t('Recent Photos')),
- '$can_post' => $can_post,
- '$upload' => array(t('Upload'), z_root().'/photos/'.App::$data['channel']['channel_address'].'/upload'),
- '$photos' => $photos,
- '$upload_form' => $upload_form,
- '$usage' => $usage_message
- ));
-
- }
-
- if((! $photos) && ($_REQUEST['aj'])) {
- $o .= '<div id="content-complete"></div>';
- echo $o;
- killme();
- }
-
-// paginate($a);
- return $o;
-}
-
diff --git a/mod/ping.php b/mod/ping.php
deleted file mode 100644
index 32bc9753e..000000000
--- a/mod/ping.php
+++ /dev/null
@@ -1,491 +0,0 @@
-<?php
-/**
- * @file mod/ping.php
- *
- */
-
-require_once('include/bbcode.php');
-require_once('include/notify.php');
-
-/**
- * @brief do several updates when pinged.
- *
- * This function does several tasks. Whenever called it checks for new messages,
- * introductions, notifications, etc. and returns a json with the results.
- *
- * @param App &$a
- * @result JSON
- */
-
-function ping_init(&$a) {
-
- $result = array();
- $notifs = array();
-
- $result['notify'] = 0;
- $result['home'] = 0;
- $result['network'] = 0;
- $result['intros'] = 0;
- $result['mail'] = 0;
- $result['register'] = 0;
- $result['events'] = 0;
- $result['events_today'] = 0;
- $result['birthdays'] = 0;
- $result['birthdays_today'] = 0;
- $result['all_events'] = 0;
- $result['all_events_today'] = 0;
- $result['notice'] = array();
- $result['info'] = array();
-
- $t0 = dba_timer();
-
- header("content-type: application/json");
-
- $vnotify = false;
-
- $item_normal = item_normal();
-
- if(local_channel()) {
- $vnotify = get_pconfig(local_channel(),'system','vnotify');
- $evdays = intval(get_pconfig(local_channel(),'system','evdays'));
- $ob_hash = get_observer_hash();
- }
-
- // if unset show all visual notification types
- if($vnotify === false)
- $vnotify = (-1);
- if($evdays < 1)
- $evdays = 3;
-
- /**
- * If you have several windows open to this site and switch to a different channel
- * in one of them, the others may get into a confused state showing you a page or options
- * on that page which were only valid under the old identity. You session has changed.
- * Therefore we send a notification of this fact back to the browser where it is picked up
- * in javascript and which reloads the page it is on so that it is valid under the context
- * of the now current channel.
- */
-
- $result['invalid'] = ((intval($_GET['uid'])) && (intval($_GET['uid']) != local_channel()) ? 1 : 0);
-
- /**
- * Send all system messages (alerts) to the browser.
- * Some are marked as informational and some represent
- * errors or serious notifications. These typically
- * will popup on the current page (no matter what page it is)
- */
-
- if(x($_SESSION, 'sysmsg')){
- foreach ($_SESSION['sysmsg'] as $m){
- $result['notice'][] = array('message' => $m);
- }
- unset($_SESSION['sysmsg']);
- }
- if(x($_SESSION, 'sysmsg_info')){
- foreach ($_SESSION['sysmsg_info'] as $m){
- $result['info'][] = array('message' => $m);
- }
- unset($_SESSION['sysmsg_info']);
- }
- if(! ($vnotify & VNOTIFY_INFO))
- $result['info'] = array();
- if(! ($vnotify & VNOTIFY_ALERT))
- $result['notice'] = array();
-
-
- if(App::$install) {
- echo json_encode($result);
- killme();
- }
-
- /**
- * Update chat presence indication (if applicable)
- */
-
- if(get_observer_hash() && (! $result['invalid'])) {
- $r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
- dbesc(get_observer_hash()),
- dbesc($_SERVER['REMOTE_ADDR'])
- );
- $basic_presence = false;
- if($r) {
- $basic_presence = true;
- q("update chatpresence set cp_last = '%s' where cp_id = %d",
- dbesc(datetime_convert()),
- intval($r[0]['cp_id'])
- );
- }
- if(! $basic_presence) {
- q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
- values( '%s', '%s', '%s', '%s' ) ",
- dbesc(get_observer_hash()),
- dbesc(datetime_convert()),
- dbesc('online'),
- dbesc($_SERVER['REMOTE_ADDR'])
- );
- }
- }
-
- /**
- * Chatpresence continued... if somebody hasn't pinged recently, they've most likely left the page
- * and shouldn't count as online anymore. We allow an expection for bots.
- */
-
- q("delete from chatpresence where cp_last < %s - INTERVAL %s and cp_client != 'auto' ",
- db_utcnow(), db_quoteinterval('3 MINUTE')
- );
-
- if((! local_channel()) || ($result['invalid'])) {
- echo json_encode($result);
- killme();
- }
-
- /**
- * Everything following is only permitted under the context of a locally authenticated site member.
- */
-
-
- /**
- * Handle "mark all xyz notifications read" requests.
- */
-
- // mark all items read
- if(x($_REQUEST, 'markRead') && local_channel()) {
- switch($_REQUEST['markRead']) {
- case 'network':
- $r = q("update item set item_unseen = 0 where item_unseen = 1 and uid = %d",
- intval(local_channel())
- );
- break;
- case 'home':
- $r = q("update item set item_unseen = 0 where item_unseen = 1 and item_wall = 1 and uid = %d",
- intval(local_channel())
- );
- break;
- case 'messages':
- $r = q("update mail set mail_seen = 1 where mail_seen = 0 and channel_id = %d ",
- intval(local_channel())
- );
- break;
- case 'all_events':
- $r = q("update event set `ignore` = 1 where `ignore` = 0 and uid = %d AND start < '%s' AND start > '%s' ",
- intval(local_channel()),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
- );
- break;
- case 'notify':
- $r = q("update notify set seen = 1 where uid = %d",
- intval(local_channel())
- );
- break;
- default:
- break;
- }
- }
-
- if(x($_REQUEST, 'markItemRead') && local_channel()) {
- $r = q("update item set item_unseen = 0 where parent = %d and uid = %d",
- intval($_REQUEST['markItemRead']),
- intval(local_channel())
- );
- }
-
-
-
- /**
- * URL ping/something will return detail for "something", e.g. a json list with which to populate a notification
- * dropdown menu.
- */
-
- if(argc() > 1 && argv(1) === 'notify') {
- $t = q("select count(*) as total from notify where uid = %d and seen = 0",
- intval(local_channel())
- );
- if($t && intval($t[0]['total']) > 49) {
- $z = q("select * from notify where uid = %d
- and seen = 0 order by date desc limit 50",
- intval(local_channel())
- );
- }
- else {
- $z1 = q("select * from notify where uid = %d
- and seen = 0 order by date desc limit 50",
- intval(local_channel())
- );
- $z2 = q("select * from notify where uid = %d
- and seen = 1 order by date desc limit %d",
- intval(local_channel()),
- intval(50 - intval($t[0]['total']))
- );
- $z = array_merge($z1,$z2);
- }
-
- if(count($z)) {
- foreach($z as $zz) {
- $notifs[] = array(
- 'notify_link' => z_root() . '/notify/view/' . $zz['id'],
- 'name' => $zz['name'],
- 'url' => $zz['url'],
- 'photo' => $zz['photo'],
- 'when' => relative_date($zz['date']),
- 'hclass' => (($zz['seen']) ? 'notify-seen' : 'notify-unseen'),
- 'message' => strip_tags(bbcode($zz['msg']))
- );
- }
- }
-
- echo json_encode(array('notify' => $notifs));
- killme();
- }
-
- if(argc() > 1 && argv(1) === 'messages') {
- $channel = App::get_channel();
- $t = q("select mail.*, xchan.* from mail left join xchan on xchan_hash = from_xchan
- where channel_id = %d and mail_seen = 0 and mail_deleted = 0
- and from_xchan != '%s' order by created desc limit 50",
- intval(local_channel()),
- dbesc($channel['channel_hash'])
- );
-
- if($t) {
- foreach($t as $zz) {
- $notifs[] = array(
- 'notify_link' => z_root() . '/mail/' . $zz['id'],
- 'name' => $zz['xchan_name'],
- 'url' => $zz['xchan_url'],
- 'photo' => $zz['xchan_photo_s'],
- 'when' => relative_date($zz['created']),
- 'hclass' => (intval($zz['mail_seen']) ? 'notify-seen' : 'notify-unseen'),
- 'message' => t('sent you a private message'),
- );
- }
- }
-
- echo json_encode(array('notify' => $notifs));
- killme();
- }
-
- if(argc() > 1 && (argv(1) === 'network' || argv(1) === 'home')) {
- $result = array();
-
- $r = q("SELECT * FROM item
- WHERE item_unseen = 1 and uid = %d $item_normal
- and author_xchan != '%s' ORDER BY created DESC limit 300",
- intval(local_channel()),
- dbesc($ob_hash)
- );
-
- if($r) {
- xchan_query($r);
- foreach($r as $item) {
- if((argv(1) === 'home') && (! intval($item['item_wall'])))
- continue;
- $result[] = format_notification($item);
- }
- }
-// logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA);
- echo json_encode(array('notify' => $result));
- killme();
- }
-
- if(argc() > 1 && (argv(1) === 'intros')) {
- $result = array();
-
- $r = q("SELECT * FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ORDER BY abook_created DESC LIMIT 50",
- intval(local_channel())
- );
-
- if($r) {
- foreach($r as $rr) {
- $result[] = array(
- 'notify_link' => z_root() . '/connections/ifpending',
- 'name' => $rr['xchan_name'],
- 'url' => $rr['xchan_url'],
- 'photo' => $rr['xchan_photo_s'],
- 'when' => relative_date($rr['abook_created']),
- 'hclass' => ('notify-unseen'),
- 'message' => t('added your channel')
- );
- }
- }
- logger('ping (intros): ' . print_r($result, true), LOGGER_DATA);
- echo json_encode(array('notify' => $result));
- killme();
- }
-
- if(argc() > 1 && (argv(1) === 'all_events')) {
- $bd_format = t('g A l F d') ; // 8 AM Friday January 18
-
- $result = array();
-
- $r = q("SELECT * FROM event left join xchan on event_xchan = xchan_hash
- WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0
- and type in ( 'event', 'birthday' )
- ORDER BY `start` DESC LIMIT 1000",
- intval(local_channel()),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
- );
-
- if($r) {
- foreach($r as $rr) {
- if($rr['adjust'])
- $md = datetime_convert('UTC', date_default_timezone_get(), $rr['start'], 'Y/m');
- else
- $md = datetime_convert('UTC', 'UTC', $rr['start'], 'Y/m');
-
- $strt = datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['start']);
- $today = ((substr($strt, 0, 10) === datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d')) ? true : false);
-
- $when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['start'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
-
- $result[] = array(
- 'notify_link' => z_root() . '/events', // FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $rr['event_hash'],
- 'name' => $rr['xchan_name'],
- 'url' => $rr['xchan_url'],
- 'photo' => $rr['xchan_photo_s'],
- 'when' => $when,
- 'hclass' => ('notify-unseen'),
- 'message' => t('posted an event')
- );
- }
- }
- logger('ping (all_events): ' . print_r($result, true), LOGGER_DATA);
- echo json_encode(array('notify' => $result));
- killme();
- }
-
-
-
- /**
- * Normal ping - just the counts, no detail
- */
-
- if($vnotify & VNOTIFY_SYSTEM) {
- $t = q("select count(*) as total from notify where uid = %d and seen = 0",
- intval(local_channel())
- );
- if($t)
- $result['notify'] = intval($t[0]['total']);
- }
-
- $t1 = dba_timer();
-
- if($vnotify & (VNOTIFY_NETWORK|VNOTIFY_CHANNEL)) {
- $r = q("SELECT id, item_wall FROM item
- WHERE item_unseen = 1 and uid = %d
- $item_normal
- and author_xchan != '%s'",
- intval(local_channel()),
- dbesc($ob_hash)
- );
-
- if($r) {
- $arr = array('items' => $r);
- call_hooks('network_ping', $arr);
-
- foreach ($r as $it) {
- if(intval($it['item_wall']))
- $result['home'] ++;
- else
- $result['network'] ++;
- }
- }
- }
- if(! ($vnotify & VNOTIFY_NETWORK))
- $result['network'] = 0;
- if(! ($vnotify & VNOTIFY_CHANNEL))
- $result['home'] = 0;
-
-
- $t2 = dba_timer();
-
- if($vnotify & VNOTIFY_INTRO) {
- $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
- intval(local_channel())
- );
-
- $t3 = dba_timer();
-
- if($intr)
- $result['intros'] = intval($intr[0]['total']);
- }
-
- $t4 = dba_timer();
- $channel = App::get_channel();
-
- if($vnotify & VNOTIFY_MAIL) {
- $mails = q("SELECT count(id) as total from mail
- WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
- intval(local_channel()),
- dbesc($channel['channel_hash'])
- );
- if($mails)
- $result['mail'] = intval($mails[0]['total']);
- }
-
- if($vnotify & VNOTIFY_REGISTER) {
- if (App::$config['system']['register_policy'] == REGISTER_APPROVE && is_site_admin()) {
- $regs = q("SELECT count(account_id) as total from account where (account_flags & %d) > 0",
- intval(ACCOUNT_PENDING)
- );
- if($regs)
- $result['register'] = intval($regs[0]['total']);
- }
- }
-
- $t5 = dba_timer();
-
- if($vnotify & (VNOTIFY_EVENT|VNOTIFY_EVENTTODAY|VNOTIFY_BIRTHDAY)) {
- $events = q("SELECT type, start, adjust FROM `event`
- WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0
- and type in ( 'event', 'birthday' )
- ORDER BY `start` ASC ",
- intval(local_channel()),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
- );
-
- if($events) {
- $result['all_events'] = count($events);
-
- if($result['all_events']) {
- $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d');
- foreach($events as $x) {
- $bd = false;
- if($x['type'] === 'birthday') {
- $result['birthdays'] ++;
- $bd = true;
- }
- else {
- $result['events'] ++;
- }
- if(datetime_convert('UTC', ((intval($x['adjust'])) ? date_default_timezone_get() : 'UTC'), $x['start'], 'Y-m-d') === $str_now) {
- $result['all_events_today'] ++;
- if($bd)
- $result['birthdays_today'] ++;
- else
- $result['events_today'] ++;
- }
- }
- }
- }
- }
- if(! ($vnotify & VNOTIFY_EVENT))
- $result['all_events'] = $result['events'] = 0;
- if(! ($vnotify & VNOTIFY_EVENTTODAY))
- $result['all_events_today'] = $result['events_today'] = 0;
- if(! ($vnotify & VNOTIFY_BIRTHDAY))
- $result['birthdays'] = 0;
-
-
- $x = json_encode($result);
-
- $t6 = dba_timer();
-
-// logger('ping timer: ' . sprintf('%01.4f %01.4f %01.4f %01.4f %01.4f %01.4f',$t6 - $t5, $t5 - $t4, $t4 - $t3, $t3 - $t2, $t2 - $t1, $t1 - $t0));
-
- echo $x;
- killme();
-}
diff --git a/mod/poco.php b/mod/poco.php
deleted file mode 100644
index 098c9a240..000000000
--- a/mod/poco.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-
-require_once('include/socgraph.php');
-
-function poco_init(&$a) {
- poco($a,false);
-}
diff --git a/mod/poke.php b/mod/poke.php
deleted file mode 100755
index 7245ceee7..000000000
--- a/mod/poke.php
+++ /dev/null
@@ -1,189 +0,0 @@
-<?php /** @file */
-
-/**
- *
- * Poke, prod, finger, or otherwise do unspeakable things to somebody - who must be a connection in your address book
- * This function can be invoked with the required arguments (verb and cid and private and possibly parent) silently via ajax or
- * other web request. You must be logged in and connected to a channel.
- * If the required arguments aren't present, we'll display a simple form to choose a recipient and a verb.
- * parent is a special argument which let's you attach this activity as a comment to an existing conversation, which
- * may have started with somebody else poking (etc.) somebody, but this isn't necessary. This can be used in the adult
- * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
- *
- * private creates a private conversation with the recipient. Otherwise your channel's default post privacy is used.
- *
- */
-
-require_once('include/items.php');
-
-function poke_init(&$a) {
-
- if(! local_channel())
- return;
-
- $uid = local_channel();
- $channel = App::get_channel();
-
- $verb = notags(trim($_REQUEST['verb']));
-
- if(! $verb)
- return;
-
- $verbs = get_poke_verbs();
-
- if(! array_key_exists($verb,$verbs))
- return;
-
- $activity = ACTIVITY_POKE . '#' . urlencode($verbs[$verb][0]);
-
- $contact_id = intval($_REQUEST['cid']);
- if(! $contact_id)
- return;
-
- $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
-
- logger('poke: verb ' . $verb . ' contact ' . $contact_id, LOGGER_DEBUG);
-
-
- $r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where abook_id = %d and abook_channel = %d LIMIT 1",
- intval($contact_id),
- intval($uid)
- );
-
- if(! $r) {
- logger('poke: no target ' . $contact_id);
- return;
- }
-
- $target = $r[0];
- $parent_item = null;
-
- if($parent) {
- $r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid
- from item where id = %d and parent = %d and uid = %d limit 1",
- intval($parent),
- intval($parent),
- intval($uid)
- );
- if($r) {
- $parent_item = $r[0];
- $parent_mid = $r[0]['mid'];
- $item_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 {
-
- $item_private = ((x($_GET,'private')) ? intval($_GET['private']) : 0);
-
- $allow_cid = (($item_private) ? '<' . $target['abook_xchan']. '>' : $channel['channel_allow_cid']);
- $allow_gid = (($item_private) ? '' : $channel['channel_allow_gid']);
- $deny_cid = (($item_private) ? '' : $channel['channel_deny_cid']);
- $deny_gid = (($item_private) ? '' : $channel['channel_deny_gid']);
- }
-
-
- $arr = array();
-
- $arr['item_wall'] = 1;
- $arr['owner_xchan'] = (($parent_item) ? $parent_item['owner_xchan'] : $channel['channel_hash']);
- $arr['parent_mid'] = (($parent_mid) ? $parent_mid : $mid);
- $arr['title'] = '';
- $arr['allow_cid'] = $allow_cid;
- $arr['allow_gid'] = $allow_gid;
- $arr['deny_cid'] = $deny_cid;
- $arr['deny_gid'] = $deny_gid;
- $arr['verb'] = $activity;
- $arr['item_private'] = $item_private;
- $arr['obj_type'] = ACTIVITY_OBJ_PERSON;
- $arr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t($verbs[$verb][0]) . ' ' . '[zrl=' . $target['xchan_url'] . ']' . $target['xchan_name'] . '[/zrl]';
-
- $obj = array(
- 'type' => ACTIVITY_OBJ_PERSON,
- 'title' => $target['xchan_name'],
- 'id' => $target['xchan_hash'],
- 'link' => array(
- array('rel' => 'alternate', 'type' => 'text/html', 'href' => $target['xchan_url']),
- array('rel' => 'photo', 'type' => $target['xchan_photo_mimetype'], 'href' => $target['xchan_photo_l'])
- ),
- );
-
- $arr['object'] = json_encode($obj);
-
- $arr['item_origin'] = 1;
- $arr['item_wall'] = 1;
- $arr['item_unseen'] = 1;
- if(! $parent_item)
- $item['item_thread_top'] = 1;
-
-
- post_activity_item($arr);
-
- return;
-}
-
-
-
-function poke_content(&$a) {
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- $name = '';
- $id = '';
-
- if(intval($_REQUEST['c'])) {
- $r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash
- where abook_id = %d and abook_channel = %d limit 1",
- intval($_REQUEST['c']),
- intval(local_channel())
- );
- if($r) {
- $name = $r[0]['xchan_name'];
- $id = $r[0]['abook_id'];
- }
- }
-
- $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : '0');
-
- $verbs = get_poke_verbs();
-
- $shortlist = array();
- foreach($verbs as $k => $v)
- if($v[1] !== 'NOTRANSLATION')
- $shortlist[] = array($k,$v[1]);
-
-
- $poke_basic = get_config('system','poke_basic');
- if($poke_basic) {
- $title = t('Poke');
- $desc = t('Poke somebody');
- }
- else {
- $title = t('Poke/Prod');
- $desc = t('Poke, prod or do other things to somebody');
- }
-
- $o = replace_macros(get_markup_template('poke_content.tpl'),array(
- '$title' => $title,
- '$poke_basic' => $poke_basic,
- '$desc' => $desc,
- '$clabel' => t('Recipient'),
- '$choice' => t('Choose what you wish to do to recipient'),
- '$verbs' => $shortlist,
- '$parent' => $parent,
- '$prv_desc' => t('Make this post private'),
- '$private' => array('private', t('Make this post private'), false, ''),
- '$submit' => t('Submit'),
- '$name' => $name,
- '$id' => $id
- ));
-
- return $o;
-
-} \ No newline at end of file
diff --git a/mod/post.php b/mod/post.php
deleted file mode 100644
index 481a4a896..000000000
--- a/mod/post.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-/**
- * @file mod/post.php
- *
- * @brief Zot endpoint.
- *
- */
-
-require_once('include/zot.php');
-
-function post_init(&$a) {
-
- if (array_key_exists('auth', $_REQUEST)) {
- $x = new Zotlabs\Zot\Auth($_REQUEST);
- exit;
- }
-
-}
-
-
-function post_post(&$a) {
-
- $z = new Zotlabs\Zot\Receiver($_REQUEST['data'],get_config('system','prvkey'), new Zotlabs\Zot\ZotHandler());
-
- // notreached;
-
- exit;
-
-}
diff --git a/mod/prate.php b/mod/prate.php
deleted file mode 100644
index 2da6855dd..000000000
--- a/mod/prate.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-function prate_init(&$a) {
- if($_SERVER['REQUEST_METHOD'] === 'post')
- return;
-
- if(! local_channel())
- return;
-
- $channel = App::get_channel();
-
- $target = argv(1);
- if(! $target)
- return;
-
- $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
- dbesc($channel['channel_hash']),
- dbesc($target)
- );
- if($r)
- json_return_and_die(array('rating' => $r[0]['xlink_rating'],'rating_text' => $r[0]['xlink_rating_text']));
- killme();
-}
-
-function prate_post(&$a) {
-
- if(! local_channel())
- return;
-
- $channel = App::get_channel();
-
- $target = trim($_REQUEST['target']);
- if(! $target)
- return;
-
- if($target === $channel['channel_hash'])
- return;
-
- $rating = intval($_POST['rating']);
- if($rating < (-10))
- $rating = (-10);
- if($rating > 10)
- $rating = 10;
-
- $rating_text = trim(escape_tags($_REQUEST['rating_text']));
-
- $signed = $target . '.' . $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($target)
- );
- 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($target),
- 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);
- }
-
- json_return_and_die(array('result' => true));;
-}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/mod/pretheme.php b/mod/pretheme.php
deleted file mode 100644
index 1974f5f00..000000000
--- a/mod/pretheme.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-function pretheme_init(&$a) {
-
- if($_REQUEST['theme']) {
- $theme = $_REQUEST['theme'];
- $info = get_theme_info($theme);
- if($info) {
- // unfortunately there will be no translation for this string
- $desc = $info['description'];
- $version = $info['version'];
- $credits = $info['credits'];
- }
- else {
- $desc = '';
- $version = '';
- $credits = '';
- }
- echo json_encode(array('img' => get_theme_screenshot($theme), 'desc' => $desc, 'version' => $version, 'credits' => $credits));
- }
- killme();
-}
diff --git a/mod/probe.php b/mod/probe.php
deleted file mode 100644
index 6408a8c4f..000000000
--- a/mod/probe.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-require_once('include/zot.php');
-
-function probe_content(&$a) {
-
- $o .= '<h3>Probe Diagnostic</h3>';
-
- $o .= '<form action="probe" method="get">';
- $o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
- $o .= '<input type="submit" name="submit" value="Submit" /></form>';
-
- $o .= '<br /><br />';
-
- if(x($_GET,'addr')) {
- $channel = App::get_channel();
- $addr = trim($_GET['addr']);
- $do_import = ((intval($_GET['import']) && is_site_admin()) ? true : false);
- $res = zot_finger($addr,$channel,false);
- $o .= '<pre>';
- if($res['success'])
- $j = json_decode($res['body'],true);
- else {
- $o .= sprintf( t('Fetching URL returns error: %1$s'),$res['error'] . "\r\n\r\n");
- $o .= "<strong>https connection failed. Trying again with auto failover to http.</strong>\r\n\r\n";
- $res = zot_finger($addr,$channel,true);
- if($res['success'])
- $j = json_decode($res['body'],true);
- else
- $o .= sprintf( t('Fetching URL returns error: %1$s'),$res['error'] . "\r\n\r\n");
-
- }
- if($do_import && $j)
- $x = import_xchan($j);
- if($j && $j['permissions'] && $j['permissions']['iv'])
- $j['permissions'] = json_decode(crypto_unencapsulate($j['permissions'],$channel['channel_prvkey']),true);
- $o .= str_replace("\n",'<br />',print_r($j,true));
- $o .= '</pre>';
- }
- return $o;
-}
diff --git a/mod/profile.php b/mod/profile.php
deleted file mode 100644
index 09bcfd56a..000000000
--- a/mod/profile.php
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php /** @file */
-
-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');
-
-
-function profile_init(&$a) {
-
- 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 profile_content(&$a, $update = 0) {
-
- if(get_config('system','block_public') && (! get_account_id()) && (! remote_channel())) {
- return login();
- }
-
- $groups = array();
-
- $tab = 'profile';
- $o = '';
-
- if(! (perm_is_allowed(App::$profile['profile_uid'],get_observer_hash(), 'view_profile'))) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
-
- $is_owner = ((local_channel()) && (local_channel() == App::$profile['profile_uid']) ? true : false);
-
- if(App::$profile['hidewall'] && (! $is_owner) && (! remote_channel())) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- $o .= profile_tabs($a, $is_owner, App::$profile['channel_address']);
-
- 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";
-
- $o .= advanced_profile($a);
- call_hooks('profile_advanced',$o);
- return $o;
-
-}
diff --git a/mod/profile_photo.php b/mod/profile_photo.php
deleted file mode 100644
index bac93555f..000000000
--- a/mod/profile_photo.php
+++ /dev/null
@@ -1,467 +0,0 @@
-<?php
-
-/* @file profile_photo.php
- @brief Module-file with functions for handling of profile-photos
-
-*/
-
-require_once('include/photo/photo_driver.php');
-require_once('include/identity.php');
-
-/* @brief Function for sync'ing permissions of profile-photos and their profile
-*
-* @param $profileid The id number of the profile to sync
-* @return void
-*/
-
-function profile_photo_set_profile_perms($profileid = '') {
-
- $allowcid = '';
- if (x($profileid)) {
-
- $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.id = %d OR profile.profile_guid = '%s' LIMIT 1", intval($profileid), dbesc($profileid));
-
- } else {
-
- logger('Resetting permissions on default-profile-photo for user'.local_channel());
- $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.uid = %d AND is_default = 1 LIMIT 1", intval(local_channel()) ); //If no profile is given, we update the default profile
- }
-
- $profile = $r[0];
- if(x($profile['id']) && x($profile['photo'])) {
- preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
- $resource_id = $resource_id[0];
-
- if (intval($profile['is_default']) != 1) {
- $r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1", intval(local_channel()) );
- $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ", intval($profile['id'])); //Should not be needed in future. Catches old int-profile-ids.
- $r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'", dbesc($profile['profile_guid']));
- $allowcid = "<" . $r0[0]['channel_hash'] . ">";
- foreach ($r1 as $entry) {
- $allowcid .= "<" . $entry['abook_xchan'] . ">";
- }
- foreach ($r2 as $entry) {
- $allowcid .= "<" . $entry['abook_xchan'] . ">";
- }
-
- q("UPDATE `photo` SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",dbesc($allowcid),dbesc($resource_id),intval($profile['uid']));
-
- } else {
- q("UPDATE `photo` SET allow_cid = '' WHERE profile = 1 AND uid = %d",intval($profile['uid'])); //Reset permissions on default profile picture to public
- }
- }
-
- return;
-}
-
-/* @brief Initalize the profile-photo edit view
- *
- * @param $a Current application
- * @return void
- *
- */
-
-function profile_photo_init(&$a) {
-
- 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 profile_photo_post(&$a) {
-
- if(! local_channel()) {
- return;
- }
-
- check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
-
- if((x($_POST,'cropfinal')) && ($_POST['cropfinal'] == 1)) {
-
- // unless proven otherwise
- $is_default_profile = 1;
-
- if($_REQUEST['profile']) {
- $r = q("select id, profile_guid, is_default, gender from profile where id = %d and uid = %d limit 1",
- intval($_REQUEST['profile']),
- intval(local_channel())
- );
- if($r) {
- $profile = $r[0];
- if(! intval($profile['is_default']))
- $is_default_profile = 0;
- }
- }
-
-
-
- // 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 * FROM photo WHERE resource_id = '%s' AND uid = %d AND scale = %d LIMIT 1",
- dbesc($image_id),
- dbesc(local_channel()),
- intval($scale));
-
- 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()) {
-
- $im->cropImage(300,$srcX,$srcY,$srcW,$srcH);
-
- $aid = get_account_id();
-
- $p = array('aid' => $aid, 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'],
- 'filename' => $base_image['filename'], 'album' => t('Profile Photos'));
-
- $p['scale'] = 4;
- $p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL);
-
- $r1 = $im->save($p);
-
- $im->scaleImage(80);
- $p['scale'] = 5;
-
- $r2 = $im->save($p);
-
- $im->scaleImage(48);
- $p['scale'] = 6;
-
- $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 >= 4 ",
- dbesc($base_image['resource_id']),
- local_channel()
- );
- return;
- }
-
- $channel = App::get_channel();
-
- // If setting for the default profile, unset the profile photo flag from any other photos I own
-
- if($is_default_profile) {
- $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d
- AND resource_id != '%s' AND `uid` = %d",
- intval(PHOTO_NORMAL),
- intval(PHOTO_PROFILE),
- dbesc($base_image['resource_id']),
- intval(local_channel())
- );
-
- send_profile_photo_activity($channel,$base_image,$profile);
-
- }
- else {
- $r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
- dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-4'),
- dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-5'),
- intval($_REQUEST['profile']),
- intval(local_channel())
- );
- }
-
- profiles_build_sync(local_channel());
-
- // We'll set the updated profile-photo timestamp even if it isn't the default profile,
- // so that browsers will do a cache update unconditionally
-
-
- $r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s'
- where xchan_hash = '%s'",
- dbesc($im->getType()),
- dbesc(datetime_convert()),
- dbesc($channel['xchan_hash'])
- );
-
- info( t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL);
-
- // Update directory in background
- proc_run('php',"include/directory.php",$channel['channel_id']);
-
- // Now copy profile-permissions to pictures, to prevent privacyleaks by automatically created folder 'Profile Pictures'
-
- profile_photo_set_profile_perms($_REQUEST['profile']);
-
-
-
- }
- else
- notice( t('Unable to process image') . EOL);
- }
-
- goaway(z_root() . '/profiles');
- return; // NOTREACHED
- }
-
-
-
- $hash = photo_new_resource();
- $smallest = 0;
-
- require_once('include/attach.php');
-
- $res = attach_store(App::get_channel(), get_observer_hash(), '', array('album' => t('Profile 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 order by scale",
- dbesc($hash),
- intval(local_channel())
- );
-
- if(! $i) {
- notice( t('Image upload failed.') . EOL );
- return;
- }
- $os_storage = false;
-
- foreach($i as $ii) {
- if(intval($ii['scale']) < 2) {
- $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 profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
-
-}
-
-
-/* @brief Generate content of profile-photo view
- *
- * @param $a Current application
- * @return void
- *
- */
-
-
-function profile_photo_content(&$a) {
-
- 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('/profile_photo', 'profile_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'] == 5)
- $havescale = true;
- }
-
- // set an already loaded photo as profile photo
-
- if(($r[0]['album'] == t('Profile Photos')) && ($havescale)) {
- // unset any existing profile photos
- $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
- intval(PHOTO_NORMAL),
- intval(PHOTO_PROFILE),
- intval(local_channel()));
-
- $r = q("UPDATE photo SET photo_usage = %d WHERE uid = %d AND resource_id = '%s'",
- intval(PHOTO_PROFILE),
- intval(local_channel()),
- dbesc($resource_id)
- );
-
- $r = q("UPDATE xchan set xchan_photo_date = '%s'
- where xchan_hash = '%s'",
- dbesc(datetime_convert()),
- dbesc($channel['xchan_hash'])
- );
-
- profile_photo_set_profile_perms(); //Reset default photo permissions to public
- proc_run('php','include/directory.php',local_channel());
- goaway(z_root() . '/profiles');
- }
-
- $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 order by scale",
- dbesc($r[0]['resource_id']),
- intval(local_channel())
- );
-
- if($i) {
- $hash = $i[0]['resource_id'];
- foreach($i as $ii) {
- if(intval($ii['scale']) < 2) {
- $smallest = intval($ii['scale']);
- }
- }
- }
- }
-
- profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
- }
-
- $profiles = q("select id, profile_name as name, is_default from profile where uid = %d",
- intval(local_channel())
- );
-
- if(! x(App::$data,'imagecrop')) {
-
- $tpl = get_markup_template('profile_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 Profile Photo'),
- '$submit' => t('Upload'),
- '$profiles' => $profiles,
- '$single' => ((count($profiles) == 1) ? true : false),
- '$profile0' => $profiles[0],
- '$form_security_token' => get_form_security_token("profile_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('profile_photo_content_end', $o);
-
- return $o;
- }
- else {
- $filename = App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'];
- $resolution = App::$data['imagecrop_resolution'];
- $tpl = get_markup_template("cropbody.tpl");
- $o .= replace_macros($tpl,array(
- '$filename' => $filename,
- '$profile' => intval($_REQUEST['profile']),
- '$resource' => App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'],
- '$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("profile_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 profile_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 < 500 || $height < 500) {
- $ph->scaleImageUp(400);
- $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;
-}
-
diff --git a/mod/profiles.php b/mod/profiles.php
deleted file mode 100644
index 75c05b634..000000000
--- a/mod/profiles.php
+++ /dev/null
@@ -1,789 +0,0 @@
-<?php
-
-require_once('include/identity.php');
-
-function profiles_init(&$a) {
-
- nav_set_selected('profiles');
-
- if(! local_channel()) {
- return;
- }
-
- if((argc() > 2) && (argv(1) === "drop") && intval(argv(2))) {
- $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d AND `is_default` = 0 LIMIT 1",
- intval(argv(2)),
- intval(local_channel())
- );
- if(! count($r)) {
- notice( t('Profile not found.') . EOL);
- goaway(z_root() . '/profiles');
- return; // NOTREACHED
- }
- $profile_guid = $r['profile_guid'];
-
- check_form_security_token_redirectOnErr('/profiles', 'profile_drop', 't');
-
- // move every contact using this profile as their default to the user default
-
- $r = q("UPDATE abook SET abook_profile = (SELECT profile_guid AS FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1) WHERE abook_profile = '%s' AND abook_channel = %d ",
- intval(local_channel()),
- dbesc($profile_guid),
- intval(local_channel())
- );
- $r = q("DELETE FROM `profile` WHERE `id` = %d AND `uid` = %d",
- intval(argv(2)),
- intval(local_channel())
- );
- if($r)
- info( t('Profile deleted.') . EOL);
-
- // @fixme this is a much more complicated sync - add any changed abook entries and
- // also add deleted flag to profile structure
- // profiles_build_sync is just here as a placeholder - it doesn't work at all here
-
- // profiles_build_sync(local_channel());
-
- goaway(z_root() . '/profiles');
- return; // NOTREACHED
- }
-
-
-
-
-
- if((argc() > 1) && (argv(1) === 'new')) {
-
-// check_form_security_token_redirectOnErr('/profiles', 'profile_new', 't');
-
- $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d",
- intval(local_channel()));
- $num_profiles = count($r0);
-
- $name = t('Profile-') . ($num_profiles + 1);
-
- $r1 = q("SELECT `name`, `photo`, `thumb` FROM `profile` WHERE `uid` = %d AND `is_default` = 1 LIMIT 1",
- intval(local_channel()));
-
- $r2 = q("INSERT INTO `profile` (`aid`, `uid` , `profile_guid`, `profile_name` , `name`, `photo`, `thumb`)
- VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
- intval(get_account_id()),
- intval(local_channel()),
- dbesc(random_string()),
- dbesc($name),
- dbesc($r1[0]['name']),
- dbesc($r1[0]['photo']),
- dbesc($r1[0]['thumb'])
- );
-
- $r3 = q("SELECT `id` FROM `profile` WHERE `uid` = %d AND `profile_name` = '%s' LIMIT 1",
- intval(local_channel()),
- dbesc($name)
- );
-
- info( t('New profile created.') . EOL);
- if(count($r3) == 1)
- goaway(z_root() . '/profiles/' . $r3[0]['id']);
-
- goaway(z_root() . '/profiles');
- }
-
- if((argc() > 2) && (argv(1) === 'clone')) {
-
- check_form_security_token_redirectOnErr('/profiles', 'profile_clone', 't');
-
- $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d",
- intval(local_channel()));
- $num_profiles = count($r0);
-
- $name = t('Profile-') . ($num_profiles + 1);
- $r1 = q("SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d LIMIT 1",
- intval(local_channel()),
- intval(App::$argv[2])
- );
- if(! count($r1)) {
- notice( t('Profile unavailable to clone.') . EOL);
- App::$error = 404;
- return;
- }
- unset($r1[0]['id']);
- $r1[0]['is_default'] = 0;
- $r1[0]['publish'] = 0;
- $r1[0]['profile_name'] = dbesc($name);
- $r1[0]['profile_guid'] = dbesc(random_string());
-
- dbesc_array($r1[0]);
-
- $r2 = dbq("INSERT INTO `profile` (`"
- . implode("`, `", array_keys($r1[0]))
- . "`) VALUES ('"
- . implode("', '", array_values($r1[0]))
- . "')" );
-
- $r3 = q("SELECT `id` FROM `profile` WHERE `uid` = %d AND `profile_name` = '%s' LIMIT 1",
- intval(local_channel()),
- dbesc($name)
- );
- info( t('New profile created.') . EOL);
-
- profiles_build_sync(local_channel());
-
- if(($r3) && (count($r3) == 1))
- goaway(z_root() . '/profiles/' . $r3[0]['id']);
-
- goaway(z_root() . '/profiles');
-
- return; // NOTREACHED
- }
-
- if((argc() > 2) && (argv(1) === 'export')) {
-
- $r1 = q("SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d LIMIT 1",
- intval(local_channel()),
- intval(argv(2))
- );
- if(! $r1) {
- notice( t('Profile unavailable to export.') . EOL);
- App::$error = 404;
- return;
- }
- header('content-type: application/octet_stream');
- header('content-disposition: attachment; filename="' . $r1[0]['profile_name'] . '.json"' );
-
- unset($r1[0]['id']);
- unset($r1[0]['aid']);
- unset($r1[0]['uid']);
- unset($r1[0]['is_default']);
- unset($r1[0]['publish']);
- unset($r1[0]['profile_name']);
- unset($r1[0]['profile_guid']);
- echo json_encode($r1[0]);
- killme();
- }
-
-
-
-
- // Run profile_load() here to make sure the theme is set before
- // we start loading content
- if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) {
- if(feature_enabled(local_channel(),'multi_profiles'))
- $id = App::$argv[1];
- else {
- $x = q("select id from profile where uid = %d and is_default = 1",
- intval(local_channel())
- );
- if($x)
- $id = $x[0]['id'];
- }
- $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval($id),
- intval(local_channel())
- );
- if(! count($r)) {
- notice( t('Profile not found.') . EOL);
- App::$error = 404;
- return;
- }
-
- $chan = App::get_channel();
-
- profile_load($a,$chan['channel_address'],$r[0]['id']);
- }
-}
-
-function profiles_post(&$a) {
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- require_once('include/activities.php');
-
- $namechanged = false;
-
-
- // import from json export file.
- // Only import fields that are allowed on this hub
-
- if(x($_FILES,'userfile')) {
- $src = $_FILES['userfile']['tmp_name'];
- $filesize = intval($_FILES['userfile']['size']);
- if($filesize) {
- $j = @json_decode(@file_get_contents($src),true);
- @unlink($src);
- if($j) {
- $fields = get_profile_fields_advanced();
- if($fields) {
- foreach($j as $jj => $v) {
- foreach($fields as $f => $n) {
- if($jj == $f) {
- $_POST[$f] = $v;
- break;
- }
- }
- }
- }
- }
- }
- }
-
- call_hooks('profile_post', $_POST);
-
-
- if((argc() > 1) && (argv(1) !== "new") && intval(argv(1))) {
- $orig = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval(App::$argv[1]),
- intval(local_channel())
- );
- if(! count($orig)) {
- notice( t('Profile not found.') . EOL);
- return;
- }
-
- check_form_security_token_redirectOnErr('/profiles', 'profile_edit');
-
- $is_default = (($orig[0]['is_default']) ? 1 : 0);
-
- $profile_name = notags(trim($_POST['profile_name']));
- if(! strlen($profile_name)) {
- notice( t('Profile Name is required.') . EOL);
- return;
- }
-
- $dob = $_POST['dob'] ? escape_tags(trim($_POST['dob'])) : '0000-00-00'; // FIXME: Needs to be validated?
-
- $y = substr($dob,0,4);
- if((! ctype_digit($y)) || ($y < 1900))
- $ignore_year = true;
- else
- $ignore_year = false;
-
- if($dob != '0000-00-00') {
- if(strpos($dob,'0000-') === 0) {
- $ignore_year = true;
- $dob = substr($dob,5);
- }
- $dob = datetime_convert('UTC','UTC',(($ignore_year) ? '1900-' . $dob : $dob),(($ignore_year) ? 'm-d' : 'Y-m-d'));
- if($ignore_year)
- $dob = '0000-' . $dob;
- }
-
- $name = escape_tags(trim($_POST['name']));
-
- if($orig[0]['name'] != $name) {
- $namechanged = true;
-
- $v = validate_channelname($name);
- if($v) {
- notice($v);
- $namechanged = false;
- $name = $orig[0]['name'];
- }
- }
-
- $pdesc = escape_tags(trim($_POST['pdesc']));
- $gender = escape_tags(trim($_POST['gender']));
- $address = escape_tags(trim($_POST['address']));
- $locality = escape_tags(trim($_POST['locality']));
- $region = escape_tags(trim($_POST['region']));
- $postal_code = escape_tags(trim($_POST['postal_code']));
- $country_name = escape_tags(trim($_POST['country_name']));
- $keywords = escape_tags(trim($_POST['keywords']));
- $marital = escape_tags(trim($_POST['marital']));
- $howlong = escape_tags(trim($_POST['howlong']));
- $sexual = escape_tags(trim($_POST['sexual']));
- $homepage = escape_tags(trim($_POST['homepage']));
- $hometown = escape_tags(trim($_POST['hometown']));
- $politic = escape_tags(trim($_POST['politic']));
- $religion = escape_tags(trim($_POST['religion']));
-
- $likes = fix_mce_lf(escape_tags(trim($_POST['likes'])));
- $dislikes = fix_mce_lf(escape_tags(trim($_POST['dislikes'])));
-
- $about = fix_mce_lf(escape_tags(trim($_POST['about'])));
- $interest = fix_mce_lf(escape_tags(trim($_POST['interest'])));
- $contact = fix_mce_lf(escape_tags(trim($_POST['contact'])));
- $channels = fix_mce_lf(escape_tags(trim($_POST['channels'])));
- $music = fix_mce_lf(escape_tags(trim($_POST['music'])));
- $book = fix_mce_lf(escape_tags(trim($_POST['book'])));
- $tv = fix_mce_lf(escape_tags(trim($_POST['tv'])));
- $film = fix_mce_lf(escape_tags(trim($_POST['film'])));
- $romance = fix_mce_lf(escape_tags(trim($_POST['romance'])));
- $work = fix_mce_lf(escape_tags(trim($_POST['work'])));
- $education = fix_mce_lf(escape_tags(trim($_POST['education'])));
-
- $hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0);
-
- require_once('include/text.php');
- linkify_tags($a, $likes, local_channel());
- linkify_tags($a, $dislikes, local_channel());
- linkify_tags($a, $about, local_channel());
- linkify_tags($a, $interest, local_channel());
- linkify_tags($a, $interest, local_channel());
- linkify_tags($a, $contact, local_channel());
- linkify_tags($a, $channels, local_channel());
- linkify_tags($a, $music, local_channel());
- linkify_tags($a, $book, local_channel());
- linkify_tags($a, $tv, local_channel());
- linkify_tags($a, $film, local_channel());
- linkify_tags($a, $romance, local_channel());
- linkify_tags($a, $work, local_channel());
- linkify_tags($a, $education, local_channel());
-
-
- $with = ((x($_POST,'with')) ? escape_tags(trim($_POST['with'])) : '');
-
- if(! strlen($howlong))
- $howlong = NULL_DATE;
- else
- $howlong = datetime_convert(date_default_timezone_get(),'UTC',$howlong);
-
- // linkify the relationship target if applicable
-
- $withchanged = false;
-
- if(strlen($with)) {
- if($with != strip_tags($orig[0]['with'])) {
- $withchanged = true;
- $prf = '';
- $lookup = $with;
- if(strpos($lookup,'@') === 0)
- $lookup = substr($lookup,1);
- $lookup = str_replace('_',' ', $lookup);
- $newname = $lookup;
-
- $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE xchan_name = '%s' AND abook_channel = %d LIMIT 1",
- dbesc($newname),
- intval(local_channel())
- );
- if(! $r) {
- $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE xchan_addr = '%s' AND abook_channel = %d LIMIT 1",
- dbesc($lookup . '@%'),
- intval(local_channel())
- );
- }
- if($r) {
- $prf = $r[0]['xchan_url'];
- $newname = $r[0]['xchan_name'];
- }
-
-
- if($prf) {
- $with = str_replace($lookup,'<a href="' . $prf . '">' . $newname . '</a>', $with);
- if(strpos($with,'@') === 0)
- $with = substr($with,1);
- }
- }
- else
- $with = $orig[0]['with'];
- }
-
- $profile_fields_basic = get_profile_fields_basic();
- $profile_fields_advanced = get_profile_fields_advanced();
- $advanced = ((feature_enabled(local_channel(),'advanced_profiles')) ? true : false);
- if($advanced)
- $fields = $profile_fields_advanced;
- else
- $fields = $profile_fields_basic;
-
- $z = q("select * from profdef where true");
- if($z) {
- foreach($z as $zz) {
- if(array_key_exists($zz['field_name'],$fields)) {
- $w = q("select * from profext where channel_id = %d and hash = '%s' and k = '%s' limit 1",
- intval(local_channel()),
- dbesc($orig[0]['profile_guid']),
- dbesc($zz['field_name'])
- );
- if($w) {
- q("update profext set v = '%s' where id = %d",
- dbesc(escape_tags(trim($_POST[$zz['field_name']]))),
- intval($w[0]['id'])
- );
- }
- else {
- q("insert into profext ( channel_id, hash, k, v ) values ( %d, '%s', '%s', '%s') ",
- intval(local_channel()),
- dbesc($orig[0]['profile_guid']),
- dbesc($zz['field_name']),
- dbesc(escape_tags(trim($_POST[$zz['field_name']])))
- );
- }
- }
- }
- }
-
- $changes = array();
- $value = '';
- if($is_default) {
- if($marital != $orig[0]['marital']) {
- $changes[] = '[color=#ff0000]&hearts;[/color] ' . t('Marital Status');
- $value = $marital;
- }
- if($withchanged) {
- $changes[] = '[color=#ff0000]&hearts;[/color] ' . t('Romantic Partner');
- $value = strip_tags($with);
- }
- if($likes != $orig[0]['likes']) {
- $changes[] = t('Likes');
- $value = $likes;
- }
- if($dislikes != $orig[0]['dislikes']) {
- $changes[] = t('Dislikes');
- $value = $dislikes;
- }
- if($work != $orig[0]['work']) {
- $changes[] = t('Work/Employment');
- }
- if($religion != $orig[0]['religion']) {
- $changes[] = t('Religion');
- $value = $religion;
- }
- if($politic != $orig[0]['politic']) {
- $changes[] = t('Political Views');
- $value = $politic;
- }
- if($gender != $orig[0]['gender']) {
- $changes[] = t('Gender');
- $value = $gender;
- }
- if($sexual != $orig[0]['sexual']) {
- $changes[] = t('Sexual Preference');
- $value = $sexual;
- }
- if($homepage != $orig[0]['homepage']) {
- $changes[] = t('Homepage');
- $value = $homepage;
- }
- if($interest != $orig[0]['interest']) {
- $changes[] = t('Interests');
- $value = $interest;
- }
- if($address != $orig[0]['address']) {
- $changes[] = t('Address');
- // New address not sent in notifications, potential privacy issues
- // in case this leaks to unintended recipients. Yes, it's in the public
- // profile but that doesn't mean we have to broadcast it to everybody.
- }
- if($locality != $orig[0]['locality'] || $region != $orig[0]['region']
- || $country_name != $orig[0]['country_name']) {
- $changes[] = t('Location');
- $comma1 = ((($locality) && ($region || $country_name)) ? ', ' : ' ');
- $comma2 = (($region && $country_name) ? ', ' : '');
- $value = $locality . $comma1 . $region . $comma2 . $country_name;
- }
-
- profile_activity($changes,$value);
-
- }
-
- $r = q("UPDATE `profile`
- SET `profile_name` = '%s',
- `name` = '%s',
- `pdesc` = '%s',
- `gender` = '%s',
- `dob` = '%s',
- `address` = '%s',
- `locality` = '%s',
- `region` = '%s',
- `postal_code` = '%s',
- `country_name` = '%s',
- `marital` = '%s',
- `with` = '%s',
- `howlong` = '%s',
- `sexual` = '%s',
- `homepage` = '%s',
- `hometown` = '%s',
- `politic` = '%s',
- `religion` = '%s',
- `keywords` = '%s',
- `likes` = '%s',
- `dislikes` = '%s',
- `about` = '%s',
- `interest` = '%s',
- `contact` = '%s',
- `channels` = '%s',
- `music` = '%s',
- `book` = '%s',
- `tv` = '%s',
- `film` = '%s',
- `romance` = '%s',
- `work` = '%s',
- `education` = '%s',
- `hide_friends` = %d
- WHERE `id` = %d AND `uid` = %d",
- dbesc($profile_name),
- dbesc($name),
- dbesc($pdesc),
- dbesc($gender),
- dbesc($dob),
- dbesc($address),
- dbesc($locality),
- dbesc($region),
- dbesc($postal_code),
- dbesc($country_name),
- dbesc($marital),
- dbesc($with),
- dbesc($howlong),
- dbesc($sexual),
- dbesc($homepage),
- dbesc($hometown),
- dbesc($politic),
- dbesc($religion),
- dbesc($keywords),
- dbesc($likes),
- dbesc($dislikes),
- dbesc($about),
- dbesc($interest),
- dbesc($contact),
- dbesc($channels),
- dbesc($music),
- dbesc($book),
- dbesc($tv),
- dbesc($film),
- dbesc($romance),
- dbesc($work),
- dbesc($education),
- intval($hide_friends),
- intval(argv(1)),
- intval(local_channel())
- );
-
- if($r)
- info( t('Profile updated.') . EOL);
-
- $r = q("select * from profile where id = %d and uid = %d limit 1",
- intval(argv(1)),
- intval(local_channel())
- );
- if($r) {
- require_once('include/zot.php');
- build_sync_packet(local_channel(),array('profile' => $r));
- }
-
- $channel = App::get_channel();
-
- if($namechanged && $is_default) {
- $r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'",
- dbesc($name),
- dbesc(datetime_convert()),
- dbesc($channel['xchan_hash'])
- );
- $r = q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'",
- dbesc($name),
- dbesc($channel['xchan_hash'])
- );
- }
-
- if($is_default) {
- // reload the info for the sidebar widget - why does this not work?
- profile_load($a,$channel['channel_address']);
- proc_run('php','include/directory.php',local_channel());
- }
- }
-}
-
-
-function profiles_content(&$a) {
-
- $o = '';
-
- $channel = App::get_channel();
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- require_once('include/identity.php');
-
- $profile_fields_basic = get_profile_fields_basic();
- $profile_fields_advanced = get_profile_fields_advanced();
-
- if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) {
- if(feature_enabled(local_channel(),'multi_profiles'))
- $id = App::$argv[1];
- else {
- $x = q("select id from profile where uid = %d and is_default = 1",
- intval(local_channel())
- );
- if($x)
- $id = $x[0]['id'];
- }
- $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval($id),
- intval(local_channel())
- );
- if(! count($r)) {
- notice( t('Profile not found.') . EOL);
- return;
- }
-
- require_once('include/profile_selectors.php');
-
-
- $editselect = 'none';
-// if(feature_enabled(local_channel(),'richtext'))
-// $editselect = 'textareas';
-
- App::$page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), array(
- '$baseurl' => z_root(),
- '$editselect' => $editselect,
- ));
-
- $advanced = ((feature_enabled(local_channel(),'advanced_profiles')) ? true : false);
- if($advanced)
- $fields = $profile_fields_advanced;
- else
- $fields = $profile_fields_basic;
-
- $hide_friends = array(
- 'hide_friends',
- t('Hide your connections list from viewers of this profile'),
- $r[0]['hide_friends'],
- '',
- array(t('No'),t('Yes'))
- );
-
- $q = q("select * from profdef where true");
- if($q) {
- $extra_fields = array();
-
- foreach($q as $qq) {
- $mine = q("select v from profext where k = '%s' and hash = '%s' and channel_id = %d limit 1",
- dbesc($qq['field_name']),
- dbesc($r[0]['profile_guid']),
- intval(local_channel())
- );
-
- if(array_key_exists($qq['field_name'],$fields)) {
- $extra_fields[] = array($qq['field_name'],$qq['field_desc'],(($mine) ? $mine[0]['v'] : ''), $qq['field_help']);
- }
- }
- }
-
-//logger('extra_fields: ' . print_r($extra_fields,true));
-
- $f = get_config('system','birthday_input_format');
- if(! $f)
- $f = 'ymd';
-
- $is_default = (($r[0]['is_default']) ? 1 : 0);
-
- $tpl = get_markup_template("profile_edit.tpl");
- $o .= replace_macros($tpl,array(
-
- '$form_security_token' => get_form_security_token("profile_edit"),
- '$profile_clone_link' => ((feature_enabled(local_channel(),'multi_profiles')) ? 'profiles/clone/' . $r[0]['id'] . '?t='
- . get_form_security_token("profile_clone") : ''),
- '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t='
- . get_form_security_token("profile_drop"),
-
- '$fields' => $fields,
- '$guid' => $r[0]['profile_guid'],
- '$banner' => t('Edit Profile Details'),
- '$submit' => t('Submit'),
- '$viewprof' => t('View this profile'),
- '$editvis' => t('Edit visibility'),
- '$coverpic' => t('Change cover photo'),
- '$profpic' => t('Change profile photo'),
- '$cr_prof' => t('Create a new profile using these settings'),
- '$cl_prof' => t('Clone this profile'),
- '$del_prof' => t('Delete this profile'),
- '$addthing' => t('Add profile things'),
- '$personal' => t('Personal'),
- '$location' => t('Location'),
- '$relation' => t('Relation'),
- '$miscellaneous'=> t('Miscellaneous'),
- '$exportable' => feature_enabled(local_channel(),'profile_export'),
- '$lbl_import' => t('Import profile from file'),
- '$lbl_export' => t('Export profile to file'),
- '$lbl_gender' => t('Your gender'),
- '$lbl_marital' => t('Marital status'),
- '$lbl_sexual' => t('Sexual preference'),
- '$baseurl' => z_root(),
- '$profile_id' => $r[0]['id'],
- '$profile_name' => array('profile_name', t('Profile name'), $r[0]['profile_name'], t('Required'), '*'),
- '$is_default' => $is_default,
- '$default' => t('This is your default profile.') . EOL . translate_scope(map_scope($channel['channel_r_profile'])),
- '$advanced' => $advanced,
- '$name' => array('name', t('Your full name'), $r[0]['name'], t('Required'), '*'),
- '$pdesc' => array('pdesc', t('Title/Description'), $r[0]['pdesc']),
- '$dob' => dob($r[0]['dob']),
- '$hide_friends' => $hide_friends,
- '$address' => array('address', t('Street address'), $r[0]['address']),
- '$locality' => array('locality', t('Locality/City'), $r[0]['locality']),
- '$region' => array('region', t('Region/State'), $r[0]['region']),
- '$postal_code' => array('postal_code', t('Postal/Zip code'), $r[0]['postal_code']),
- '$country_name' => array('country_name', t('Country'), $r[0]['country_name']),
- '$gender' => gender_selector($r[0]['gender']),
- '$gender_min' => gender_selector_min($r[0]['gender']),
- '$marital' => marital_selector($r[0]['marital']),
- '$marital_min' => marital_selector_min($r[0]['marital']),
- '$with' => array('with', t("Who (if applicable)"), $r[0]['with'], t('Examples: cathy123, Cathy Williams, cathy@example.com')),
- '$howlong' => array('howlong', t('Since (date)'), ($r[0]['howlong'] === NULL_DATE ? '' : datetime_convert('UTC',date_default_timezone_get(),$r[0]['howlong']))),
- '$sexual' => sexpref_selector($r[0]['sexual']),
- '$sexual_min' => sexpref_selector_min($r[0]['sexual']),
- '$about' => array('about', t('Tell us about yourself'), $r[0]['about']),
- '$homepage' => array('homepage', t('Homepage URL'), $r[0]['homepage']),
- '$hometown' => array('hometown', t('Hometown'), $r[0]['hometown']),
- '$politic' => array('politic', t('Political views'), $r[0]['politic']),
- '$religion' => array('religion', t('Religious views'), $r[0]['religion']),
- '$keywords' => array('keywords', t('Keywords used in directory listings'), $r[0]['keywords'], t('Example: fishing photography software')),
- '$likes' => array('likes', t('Likes'), $r[0]['likes']),
- '$dislikes' => array('dislikes', t('Dislikes'), $r[0]['dislikes']),
- '$music' => array('music', t('Musical interests'), $r[0]['music']),
- '$book' => array('book', t('Books, literature'), $r[0]['book']),
- '$tv' => array('tv', t('Television'), $r[0]['tv']),
- '$film' => array('film', t('Film/Dance/Culture/Entertainment'), $r[0]['film']),
- '$interest' => array('interest', t('Hobbies/Interests'), $r[0]['interest']),
- '$romance' => array('romance',t('Love/Romance'), $r[0]['romance']),
- '$work' => array('work', t('Work/Employment'), $r[0]['work']),
- '$education' => array('education', t('School/Education'), $r[0]['education']),
- '$contact' => array('contact', t('Contact information and social networks'), $r[0]['contact']),
- '$channels' => array('channels', t('My other channels'), $r[0]['channels']),
- '$extra_fields' => $extra_fields,
- ));
-
- $arr = array('profile' => $r[0], 'entry' => $o);
- call_hooks('profile_edit', $arr);
-
- return $o;
- }
- else {
-
- $r = q("SELECT * FROM `profile` WHERE `uid` = %d",
- local_channel());
- if(count($r)) {
-
- $tpl = get_markup_template('profile_entry.tpl');
- foreach($r as $rr) {
- $profiles .= replace_macros($tpl, array(
- '$photo' => $rr['thumb'],
- '$id' => $rr['id'],
- '$alt' => t('Profile Image'),
- '$profile_name' => $rr['profile_name'],
- '$visible' => (($rr['is_default'])
- ? '<strong>' . translate_scope(map_scope($channel['channel_r_profile'])) . '</strong>'
- : '<a href="' . z_root() . '/profperm/' . $rr['id'] . '" />' . t('Edit visibility') . '</a>')
- ));
- }
-
- $tpl_header = get_markup_template('profile_listing_header.tpl');
- $o .= replace_macros($tpl_header,array(
- '$header' => t('Edit Profiles'),
- '$cr_new' => t('Create New'),
- '$cr_new_link' => 'profiles/new?t=' . get_form_security_token("profile_new"),
- '$profiles' => $profiles
- ));
-
-
-
-
- }
- return $o;
- }
-
-}
diff --git a/mod/profperm.php b/mod/profperm.php
deleted file mode 100644
index 2e3f708c8..000000000
--- a/mod/profperm.php
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php
-
-require_once('include/Contact.php');
-
-function profperm_init(&$a) {
-
- if(! local_channel())
- return;
-
- $channel = App::get_channel();
- $which = $channel['channel_address'];
-
- $profile = App::$argv[1];
-
- profile_load($a,$which,$profile);
-
-}
-
-
-function profperm_content(&$a) {
-
- if(! local_channel()) {
- notice( t('Permission denied') . EOL);
- return;
- }
-
-
- if(argc() < 2) {
- notice( t('Invalid profile identifier.') . EOL );
- return;
- }
-
- // Switch to text mod 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;
-
-
- if((argc() > 2) && intval(argv(1)) && intval(argv(2))) {
- $r = q("SELECT abook_id FROM abook WHERE abook_id = %d and abook_channel = %d limit 1",
- intval(argv(2)),
- intval(local_channel())
- );
- if($r)
- $change = intval(argv(2));
- }
-
-
- if((argc() > 1) && (intval(argv(1)))) {
- $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d AND `is_default` = 0 LIMIT 1",
- intval(argv(1)),
- intval(local_channel())
- );
- if(! $r) {
- notice( t('Invalid profile identifier.') . EOL );
- return;
- }
-
- $profile = $r[0];
-
- $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_profile = '%s'",
- intval(local_channel()),
- dbesc($profile['profile_guid'])
- );
-
- $ingroup = array();
- if($r)
- foreach($r as $member)
- $ingroup[] = $member['abook_id'];
-
- $members = $r;
-
- if($change) {
- if(in_array($change,$ingroup)) {
- q("UPDATE abook SET abook_profile = '' WHERE abook_id = %d AND abook_channel = %d",
- intval($change),
- intval(local_channel())
- );
- }
- else {
- q("UPDATE abook SET abook_profile = '%s' WHERE abook_id = %d AND abook_channel = %d",
- dbesc($profile['profile_guid']),
- intval($change),
- intval(local_channel())
- );
-
- }
-
-
- //Time to update the permissions on the profile-pictures as well
- require_once('mod/profile_photo.php');
- profile_photo_set_profile_perms($profile['id']);
-
- $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_profile = '%s'",
- intval(local_channel()),
- dbesc($profile['profile_guid'])
- );
-
- $members = $r;
-
- $ingroup = array();
- if(count($r))
- foreach($r as $member)
- $ingroup[] = $member['abook_id'];
- }
-
- $o .= '<h2>' . t('Profile Visibility Editor') . '</h2>';
-
- $o .= '<h3>' . t('Profile') . ' \'' . $profile['profile_name'] . '\'</h3>';
-
- $o .= '<div id="prof-edit-desc">' . t('Click on a contact to add or remove.') . '</div>';
-
- }
-
- $o .= '<div id="prof-update-wrapper">';
- if($change)
- $o = '';
-
- $o .= '<div id="prof-members-title">';
- $o .= '<h3>' . t('Visible To') . '</h3>';
- $o .= '</div>';
- $o .= '<div id="prof-members">';
-
- $textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : false);
-
- foreach($members as $member) {
- if($member['xchan_url']) {
- $member['click'] = 'profChangeMember(' . $profile['id'] . ',' . $member['abook_id'] . '); return false;';
- $o .= micropro($member,true,'mpprof', $textmode);
- }
- }
- $o .= '</div><div id="prof-members-end"></div>';
- $o .= '<hr id="prof-separator" />';
-
- $o .= '<div id="prof-all-contcts-title">';
- $o .= '<h3>' . t("All Connections") . '</h3>';
- $o .= '</div>';
- $o .= '<div id="prof-all-contacts">';
-
- $r = abook_connections(local_channel());
-
- if($r) {
- $textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : false);
- foreach($r as $member) {
- if(! in_array($member['abook_id'],$ingroup)) {
- $member['click'] = 'profChangeMember(' . $profile['id'] . ',' . $member['abook_id'] . '); return false;';
- $o .= micropro($member,true,'mpprof',$textmode);
- }
- }
- }
-
- $o .= '</div><div id="prof-all-contacts-end"></div>';
-
- if($change) {
- echo $o;
- killme();
- }
- $o .= '</div>';
- return $o;
-
-}
-
diff --git a/mod/public.php b/mod/public.php
deleted file mode 100644
index fd89e0776..000000000
--- a/mod/public.php
+++ /dev/null
@@ -1,163 +0,0 @@
-<?php
-
-require_once('include/conversation.php');
-
-function public_content(&$a, $update = 0, $load = false) {
-
- if($load)
- $_SESSION['loadtime'] = datetime_convert();
-
-
- if(get_config('system','block_public') && (! get_account_id()) && (! remote_channel())) {
- return login();
- }
-
-
- if(get_config('system','disable_discover_tab'))
- return;
-
- $item_normal = item_normal();
-
- if(! $update) {
-
- $maxheight = get_config('system','home_divmore_height');
- if(! $maxheight)
- $maxheight = 400;
-
- $o .= '<div id="live-public"></div>' . "\r\n";
- $o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
- . "; 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' => 'public',
- '$uid' => ((local_channel()) ? local_channel() : '0'),
- '$gid' => '0',
- '$cid' => '0',
- '$cmin' => '0',
- '$cmax' => '99',
- '$star' => '0',
- '$liked' => '0',
- '$conv' => '0',
- '$spam' => '0',
- '$fh' => '1',
- '$nouveau' => '0',
- '$wall' => '0',
- '$list' => '0',
- '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
- '$search' => '',
- '$order' => 'comment',
- '$file' => '',
- '$cats' => '',
- '$tags' => '',
- '$dend' => '',
- '$mid' => '',
- '$verb' => '',
- '$dbegin' => ''
- ));
- }
-
- if($update && ! $load) {
- // only setup pagination on initial page view
- $pager_sql = '';
- }
- else {
- App::set_pager_itemspage(20);
- $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
- }
-
- require_once('include/identity.php');
- require_once('include/security.php');
-
- if(get_config('system','site_firehose')) {
- $uids = " and item.uid in ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) and item_private = 0 and item_wall = 1 ";
- }
- else {
- $sys = get_sys_channel();
- $uids = " and item.uid = " . intval($sys['channel_id']) . " ";
- $sql_extra = item_permissions_sql($sys['channel_id']);
- App::$data['firehose'] = intval($sys['channel_id']);
- }
-
- if(get_config('system','public_list_mode'))
- $page_mode = 'list';
- else
- $page_mode = 'client';
-
-
- $simple_update = (($update) ? " and item.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 = '';
-
- //logger('update: ' . $update . ' load: ' . $load);
-
- if($update) {
-
- $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.author_xchan = abook.abook_xchan
- 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 "
- );
-
-
- }
- elseif($update) {
-
- $r = q("SELECT distinct item.id AS item_id, $ordering FROM item
- left join abook on item.author_xchan = abook.abook_xchan
- WHERE true $uids $item_normal
- AND item.parent = item.id $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,(-1));
- $items = fetch_post_tags($items,true);
- $items = conv_sort($items,$ordering);
- }
- else {
- $items = array();
- }
-
- }
-
- // fake it
- $mode = ('network');
-
- $o .= conversation($a,$items,$mode,$update,$page_mode);
-
- if(($items) && (! $update))
- $o .= alt_pager($a,count($items));
-
- return $o;
-
-} \ No newline at end of file
diff --git a/mod/pubsites.php b/mod/pubsites.php
deleted file mode 100644
index dc6b09d9b..000000000
--- a/mod/pubsites.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-function pubsites_content(&$a) {
- require_once('include/dir_fns.php');
- $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);
- $url = $directory['url'] . '/dirsearch';
- }
- $url .= '/sites';
-
- $o .= '<div class="generic-content-wrapper">';
-
- $o .= '<div class="section-title-wrapper"><h2>' . t('Public Hubs') . '</h2></div>';
-
- $o .= '<div class="section-content-tools-wrapper"><div class="descriptive-text">' .
- t('The listed hubs allow public registration for the $Projectname network. All hubs in the network are interlinked so membership on any of them conveys membership in the network as a whole. Some hubs may require subscription or provide tiered service plans. The hub itself <strong>may</strong> provide additional details.') . '</div>' . EOL;
-
- $ret = z_fetch_url($url);
- if($ret['success']) {
- $j = json_decode($ret['body'],true);
- if($j) {
- $o .= '<table class="table table-striped table-hover"><tr><td>' . t('Hub URL') . '</td><td>' . t('Access Type') . '</td><td>' . t('Registration Policy') . '</td><td colspan="2">' . t('Ratings') . '</td></tr>';
- if($j['sites']) {
- foreach($j['sites'] as $jj) {
- if($jj['project'] !== Zotlabs\Project\System::get_platform_name())
- continue;
- $host = strtolower(substr($jj['url'],strpos($jj['url'],'://')+3));
- $rate_links = ((local_channel()) ? '<td><a href="rate?f=&target=' . $host . '" class="btn-btn-default"><i class="icon-check"></i> ' . t('Rate') . '</a></td>' : '');
- $location = '';
- if(!empty($jj['location'])) {
- $location = '<p title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="icon-globe"></i> ' . $jj['location'] . '</p>';
- }
- else {
- $location = '<br />&nbsp;';
- }
- $urltext = str_replace(array('https://'), '', $jj['url']);
- $o .= '<tr><td><a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" ><i class="icon-link"></i> ' . $urltext . '</a>' . $location . '</td><td>' . $jj['access'] . '</td><td>' . $jj['register'] . '</td><td><a href="ratings/' . $host . '" class="btn-btn-default"><i class="icon-eye-open"></i> ' . t('View') . '</a></td>' . $rate_links . '</tr>';
- }
- }
-
- $o .= '</table>';
-
- $o .= '</div></div>';
-
- }
- }
- return $o;
-}
diff --git a/mod/randprof.php b/mod/randprof.php
deleted file mode 100644
index 124117e96..000000000
--- a/mod/randprof.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-
-function randprof_init(&$a) {
- require_once('include/Contact.php');
- $x = random_profile();
- if($x)
- goaway(chanlink_url($x));
-
- /** FIXME this doesn't work at the moment as a fallback */
- goaway(z_root() . '/profile');
-}
diff --git a/mod/rate.php b/mod/rate.php
deleted file mode 100644
index 41e06e794..000000000
--- a/mod/rate.php
+++ /dev/null
@@ -1,173 +0,0 @@
-<?php
-
-
-function rate_init(&$a) {
-
- if(! local_channel())
- return;
-
- $channel = App::get_channel();
-
- $target = $_REQUEST['target'];
- if(! $target)
- return;
-
- App::$data['target'] = $target;
-
- if($target) {
- $r = q("SELECT * FROM xchan where xchan_hash like '%s' LIMIT 1",
- dbesc($target)
- );
- if($r) {
- App::$poi = $r[0];
- }
- else {
- $r = q("select * from site where site_url like '%s' and site_type = %d",
- dbesc('%' . $target),
- intval(SITE_TYPE_ZOT)
- );
- if($r) {
- App::$data['site'] = $r[0];
- App::$data['site']['site_url'] = strtolower($r[0]['site_url']);
- }
- }
- }
-
-
- return;
-
-}
-
-
-function rate_post(&$a) {
-
- if(! local_channel())
- return;
-
- if(! App::$data['target'])
- return;
-
- if(! $_REQUEST['execute'])
- return;
-
- $channel = App::get_channel();
-
- $rating = intval($_POST['rating']);
- if($rating < (-10))
- $rating = (-10);
- if($rating > 10)
- $rating = 10;
-
- $rating_text = trim(escape_tags($_REQUEST['rating_text']));
-
- $signed = App::$data['target'] . '.' . $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(App::$data['target'])
- );
-
- 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(App::$data['target']),
- 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(App::$data['target'])
- );
- if($z)
- $record = $z[0]['xlink_id'];
- }
-
- if($record) {
- proc_run('php','include/ratenotif.php','rating',$record);
- }
-
-}
-
-
-
-function rate_content(&$a) {
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
-// if(! App::$data['target']) {
-// notice( t('No recipients.') . EOL);
-// return;
-// }
-
- $poco_rating = get_config('system','poco_rating_enable');
- if((! $poco_rating) && ($poco_rating !== false)) {
- notice('Ratings are disabled on this site.');
- return;
- }
-
- $channel = App::get_channel();
-
- $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
- dbesc($channel['channel_hash']),
- dbesc(App::$data['target'])
- );
- if($r) {
- App::$data['xlink'] = $r[0];
- $rating_val = $r[0]['xlink_rating'];
- $rating_text = $r[0]['xlink_rating_text'];
- }
- else {
- $rating_val = 0;
- $rating_text = '';
- }
-
- // 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;
- }
-
- $o = replace_macros(get_markup_template('rating_form.tpl'),array(
- '$header' => t('Rating'),
- '$website' => t('Website:'),
- '$site' => ((App::$data['site']) ? '<a href="' . App::$data['site']['site_url'] . '" >' . App::$data['site']['site_url'] . '</a>' : ''),
- 'target' => App::$data['target'],
- '$tgt_name' => ((App::$poi && App::$poi['xchan_name']) ? App::$poi['xchan_name'] : sprintf( t('Remote Channel [%s] (not yet known on this site)'), substr(App::$data['target'],0,16))),
- '$lbl_rating' => t('Rating (this information is public)'),
- '$lbl_rating_txt' => t('Optionally explain your rating (this information is public)'),
- '$rating_txt' => $rating_text,
- '$rating' => $rating,
- '$rating_val' => $rating_val,
- '$slide' => $slide,
- '$submit' => t('Submit')
- ));
-
- return $o;
-
-} \ No newline at end of file
diff --git a/mod/ratings.php b/mod/ratings.php
deleted file mode 100644
index d99be974c..000000000
--- a/mod/ratings.php
+++ /dev/null
@@ -1,110 +0,0 @@
-<?php
-
-require_once('include/dir_fns.php');
-
-function ratings_init(&$a) {
-
- if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
- return;
- }
-
- if(local_channel())
- load_contact_links(local_channel());
-
- $dirmode = intval(get_config('system','directory_mode'));
-
- $x = find_upstream_directory($dirmode);
- if($x)
- $url = $x['url'];
-
- $poco_rating = get_config('system','poco_rating_enable');
- // if unset default to enabled
- if($poco_rating === false)
- $poco_rating = true;
-
- if(! $poco_rating)
- return;
-
- if(argc() > 1)
- $hash = argv(1);
-
- if(! $hash) {
- notice('Must supply a channel identififier.');
- return;
- }
-
- $results = false;
-
- $x = z_fetch_url($url . '/ratingsearch/' . urlencode($hash));
-
-
- if($x['success'])
- $results = json_decode($x['body'],true);
-
-
- if((! $results) || (! $results['success'])) {
-
- notice('No results.');
- return;
- }
-
- if(array_key_exists('xchan_hash',$results['target']))
- App::$poi = $results['target'];
-
- $friends = array();
- $others = array();
-
- if($results['ratings']) {
- foreach($results['ratings'] as $n) {
- if(is_array(App::$contacts) && array_key_exists($n['xchan_hash'],App::$contacts))
- $friends[] = $n;
- else
- $others[] = $n;
- }
- }
-
- App::$data = array('target' => $results['target'], 'results' => array_merge($friends,$others));
-
- if(! App::$data['results']) {
- notice( t('No ratings') . EOL);
- }
-
- return;
-}
-
-
-
-
-
-function ratings_content(&$a) {
-
- if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
- notice( t('Public access denied.') . EOL);
- return;
- }
-
- $poco_rating = get_config('system','poco_rating_enable');
- // if unset default to enabled
- if($poco_rating === false)
- $poco_rating = true;
-
- if(! $poco_rating)
- return;
-
- $site_target = ((array_key_exists('target',App::$data) && array_key_exists('site_url',App::$data['target'])) ?
- '<a href="' . App::$data['target']['site_url'] . '" >' . App::$data['target']['site_url'] . '</a>' : '');
-
-
- $o = replace_macros(get_markup_template('prep.tpl'),array(
- '$header' => t('Ratings'),
- '$rating_lbl' => t('Rating: ' ),
- '$website' => t('Website: '),
- '$site' => $site_target,
- '$rating_text_lbl' => t('Description: '),
- '$raters' => App::$data['results']
- ));
-
- return $o;
-}
-
- \ No newline at end of file
diff --git a/mod/ratingsearch.php b/mod/ratingsearch.php
deleted file mode 100644
index 173dd39ff..000000000
--- a/mod/ratingsearch.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-
-function ratingsearch_init(&$a) {
-
- $ret = array('success' => false);
-
- $dirmode = intval(get_config('system','directory_mode'));
-
- if($dirmode == DIRECTORY_MODE_NORMAL) {
- $ret['message'] = 'This site is not a directory server.';
- json_return_and_die($ret);
- }
-
- if(argc() > 1)
- $hash = argv(1);
-
- if(! $hash) {
- $ret['message'] = 'No channel identifier';
- json_return_and_die($ret);
- }
-
- if(strpos($hash,'@')) {
- $r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
- dbesc($hash)
- );
- if($r)
- $hash = $r[0]['hubloc_hash'];
- }
-
- $p = q("select * from xchan where xchan_hash like '%s'",
- dbesc($hash . '%')
- );
-
- if($p)
- $target = $p[0]['xchan_hash'];
- else {
- $p = q("select * from site where site_url like '%s' and site_type = %d ",
- dbesc('%' . $hash),
- intval(SITE_TYPE_ZOT)
- );
- if($p) {
- $target = strtolower($hash);
- }
- else {
- $ret['message'] = 'Rating target not found';
- json_return_and_die($ret);
- }
- }
-
- if($p)
- $ret['target'] = $p[0];
-
- $ret['success'] = true;
-
- $r = q("select * from xlink left join xchan on xlink_xchan = xchan_hash
- where xlink_link = '%s' and xlink_rating != 0 and xlink_static = 1 order by xchan_name asc",
- dbesc($target)
- );
-
- if($r) {
- $ret['ratings'] = $r;
- }
- else
- $ret['ratings'] = array();
-
- json_return_and_die($ret);
-
-}
-
diff --git a/mod/rbmark.php b/mod/rbmark.php
deleted file mode 100644
index 979f96f85..000000000
--- a/mod/rbmark.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php /** @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');
-require_once('include/zot.php');
-require_once('include/bookmarks.php');
-
-/**
- * remote bookmark
- *
- * https://yoursite/rbmark?f=&title=&url=&private=&remote_return=
- *
- * This can be called via either GET or POST, use POST for long body content as suhosin often limits GET parameter length
- *
- * f= placeholder, often required
- * title= link text
- * url= URL to bookmark
- * ischat=1 if this bookmark is a chatroom
- * private= Don't share this link
- * remote_return= absolute URL to return after posting is finished
- *
- */
-
-function rbmark_post(&$a) {
- if($_POST['submit'] !== t('Save'))
- return;
-
- logger('rbmark_post: ' . print_r($_REQUEST,true));
-
- $channel = App::get_channel();
-
- $t = array('url' => escape_tags($_REQUEST['url']),'term' => escape_tags($_REQUEST['title']));
- bookmark_add($channel,$channel,$t,((x($_REQUEST,'private')) ? intval($_REQUEST['private']) : 0),
- array('menu_id' => ((x($_REQUEST,'menu_id')) ? intval($_REQUEST['menu_id']) : 0),
- 'menu_name' => ((x($_REQUEST,'menu_name')) ? escape_tags($_REQUEST['menu_name']) : ''),
- 'ischat' => ((x($_REQUEST['ischat'])) ? intval($_REQUEST['ischat']) : 0)
- ));
-
- goaway(z_root() . '/bookmarks');
-
-}
-
-
-function rbmark_content(&$a) {
-
- $o = '';
-
- if(! local_channel()) {
-
- // The login procedure is going to bugger our $_REQUEST variables
- // so save them in the session.
-
- if(array_key_exists('url',$_REQUEST)) {
- $_SESSION['bookmark'] = $_REQUEST;
- }
- return login();
- }
-
- // If we have saved rbmark session variables, but nothing in the current $_REQUEST, recover the saved variables
-
- if((! array_key_exists('url',$_REQUEST)) && (array_key_exists('bookmark',$_SESSION))) {
- $_REQUEST = $_SESSION['bookmark'];
- unset($_SESSION['bookmark']);
- }
-
- if($_REQUEST['remote_return']) {
- $_SESSION['remote_return'] = $_REQUEST['remote_return'];
- }
- if(argc() > 1 && argv(1) === 'return') {
- if($_SESSION['remote_return'])
- goaway($_SESSION['remote_return']);
- goaway(z_root() . '/bookmarks');
- }
-
- $channel = App::get_channel();
-
-
- $m = menu_list($channel['channel_id'],'',MENU_BOOKMARK);
-
- $menus = array();
- if($m) {
- $menus = array(0 => '');
- foreach($m as $n) {
- $menus[$n['menu_id']] = $n['menu_name'];
- }
- }
- $menu_select = array('menu_id',t('Select a bookmark folder'),false,'',$menus);
-
-
- $o .= replace_macros(get_markup_template('rbmark.tpl'), array(
-
- '$header' => t('Save Bookmark'),
- '$url' => array('url',t('URL of bookmark'),escape_tags($_REQUEST['url'])),
- '$title' => array('title',t('Description'),escape_tags($_REQUEST['title'])),
- '$ischat' => ((x($_REQUEST,'ischat')) ? intval($_REQUEST['ischat']) : 0),
- '$private' => ((x($_REQUEST,'private')) ? intval($_REQUEST['private']) : 0),
- '$submit' => t('Save'),
- '$menu_name' => array('menu_name',t('Or enter new bookmark folder name'),'',''),
- '$menus' => $menu_select
-
- ));
-
-
-
-
-
-
- return $o;
-
-}
-
-
diff --git a/mod/regdir.php b/mod/regdir.php
deleted file mode 100644
index 7168c3373..000000000
--- a/mod/regdir.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-
-/**
- * With args, register a directory server for this realm.
- * With no args, return a JSON array of directory servers for this realm.
- *
- * @FIXME Not yet implemented: Some realms may require authentication to join their realm.
- * The RED_GLOBAL realm does not require authentication.
- * We would then need a flag in the site table to indicate that they've been
- * validated by the PRIMARY directory for that realm. Sites claiming to be PRIMARY
- * but are not the realm PRIMARY will be marked invalid.
- *
- * @param App &$a
- */
-function regdir_init(&$a) {
-
- $result = array('success' => false);
-
- $url = $_REQUEST['url'];
- $access_token = $_REQUEST['t'];
- $valid = 0;
-
- // we probably don't need the realm as we will find out in the probe.
- // What we may want to die is throw an error if you're trying to register in a different realm
- // so this configuration issue can be discovered.
-
- $realm = $_REQUEST['realm'];
- if(! $realm)
- $realm = DIRECTORY_REALM;
-
- if($realm === DIRECTORY_REALM) {
- $valid = 1;
- } else {
- $token = get_config('system','realm_token');
- if($token && $access_token != $token) {
- $result['message'] = 'This realm requires an access token';
- return;
- }
- $valid = 1;
- }
-
- $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);
- }
-
- $m = null;
- if ($url) {
- $m = parse_url($url);
-
- if ((! $m) || ((! @dns_get_record($m['host'], DNS_A + DNS_CNAME + DNS_PTR)) && (! filter_var($m['host'], FILTER_VALIDATE_IP) ))) {
-
- $result['message'] = 'unparseable url';
- json_return_and_die($result);
- }
-
- $f = zot_finger('[system]@' . $m['host']);
- if($f['success']) {
- $j = json_decode($f['body'],true);
- if($j['success'] && $j['guid']) {
- $x = import_xchan($j);
- if($x['success']) {
- $result['success'] = true;
- }
- }
- }
-
- if(! $result['success'])
- $valid = 0;
-
- q("update site set site_valid = %d where site_url = '%s' limit 1",
- intval($valid),
- strtolower($url)
- );
-
- json_return_and_die($result);
- } else {
-
- // We can put this in the sql without the condition after 31 august 2015 assuming
- // most directory servers will have updated by then
- // This just makes sure it happens if I forget
-
- $sql_extra = ((datetime_convert() > datetime_convert('UTC','UTC','2015-08-31')) ? ' and site_valid = 1 ' : '' );
- if ($dirmode == DIRECTORY_MODE_STANDALONE) {
- $r = array(array('site_url' => z_root()));
- } else {
- $r = q("select site_url from site where site_flags in ( 1, 2 ) and site_realm = '%s' and site_type = %d $sql_extra ",
- dbesc(get_directory_realm()),
- intval(SITE_TYPE_ZOT)
- );
- }
- if ($r) {
- $result['success'] = true;
- $result['directories'] = array();
- foreach ($r as $rr)
- $result['directories'][] = $rr['site_url'];
-
- json_return_and_die($result);
- }
- }
- json_return_and_die($result);
-} \ No newline at end of file
diff --git a/mod/register.php b/mod/register.php
deleted file mode 100644
index 712691547..000000000
--- a/mod/register.php
+++ /dev/null
@@ -1,264 +0,0 @@
-<?php
-
-require_once('include/identity.php');
-
-function register_init(&$a) {
-
- $result = null;
- $cmd = ((argc() > 1) ? argv(1) : '');
-
- // Provide a stored request for somebody desiring a connection
- // when they first need to register someplace. Once they've
- // created a channel, we'll try to revive the connection request
- // and process it.
-
- if($_REQUEST['connect'])
- $_SESSION['connect'] = $_REQUEST['connect'];
-
- switch($cmd) {
- case 'invite_check.json':
- $result = check_account_invite($_REQUEST['invite_code']);
- break;
- case 'email_check.json':
- $result = check_account_email($_REQUEST['email']);
- break;
- case 'password_check.json':
- $result = check_account_password($_REQUEST['password']);
- break;
- default:
- break;
- }
- if($result) {
- json_return_and_die($result);
- }
-}
-
-
-function register_post(&$a) {
-
- $max_dailies = intval(get_config('system','max_daily_registrations'));
- if($max_dailies) {
- $r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s",
- db_utcnow(), db_quoteinterval('1 day')
- );
- if($r && $r[0]['total'] >= $max_dailies) {
- notice( t('Maximum daily site registrations exceeded. Please try again tomorrow.') . EOL);
- return;
- }
- }
-
- if(! x($_POST,'tos')) {
- notice( t('Please indicate acceptance of the Terms of Service. Registration failed.') . EOL);
- return;
- }
-
- $policy = get_config('system','register_policy');
-
- $email_verify = get_config('system','verify_email');
-
-
- switch($policy) {
-
- case REGISTER_OPEN:
- $flags = ACCOUNT_OK;
- break;
-
- case REGISTER_APPROVE:
- $flags = ACCOUNT_BLOCKED | ACCOUNT_PENDING;
- break;
-
- default:
- case REGISTER_CLOSED:
- if(! is_site_admin()) {
- notice( t('Permission denied.') . EOL );
- return;
- }
- $flags = ACCOUNT_BLOCKED;
- break;
- }
-
- if($email_verify && $policy == REGISTER_OPEN)
- $flags = $flags | ACCOUNT_UNVERIFIED;
-
-
- if((! $_POST['password']) || ($_POST['password'] !== $_POST['password2'])) {
- notice( t('Passwords do not match.') . EOL);
- return;
- }
-
- $arr = $_POST;
- $arr['account_flags'] = $flags;
-
- $result = create_account($arr);
-
- if(! $result['success']) {
- notice($result['message']);
- return;
- }
- require_once('include/security.php');
-
-
- if($_REQUEST['name'])
- set_aconfig($result['account']['account_id'],'register','channel_name',$_REQUEST['name']);
- if($_REQUEST['nickname'])
- set_aconfig($result['account']['account_id'],'register','channel_address',$_REQUEST['nickname']);
- if($_REQUEST['permissions_role'])
- set_aconfig($result['account']['account_id'],'register','permissions_role',$_REQUEST['permissions_role']);
-
-
- $using_invites = intval(get_config('system','invitation_only'));
- $num_invites = intval(get_config('system','number_invites'));
- $invite_code = ((x($_POST,'invite_code')) ? notags(trim($_POST['invite_code'])) : '');
-
- if($using_invites && $invite_code) {
- q("delete * from register where hash = '%s'", dbesc($invite_code));
- // @FIXME - this also needs to be considered when using 'invites_remaining' in mod/invite.php
- set_aconfig($result['account']['account_id'],'system','invites_remaining',$num_invites);
- }
-
- if($policy == REGISTER_OPEN ) {
- if($email_verify) {
- $res = verify_email_address($result);
- }
- else {
- $res = send_register_success_email($result['email'],$result['password']);
- }
- if($res) {
- info( t('Registration successful. Please check your email for validation instructions.') . EOL ) ;
- }
- }
- elseif($policy == REGISTER_APPROVE) {
- $res = send_reg_approval_email($result);
- if($res) {
- info( t('Your registration is pending approval by the site owner.') . EOL ) ;
- }
- else {
- notice( t('Your registration can not be processed.') . EOL);
- }
- goaway(z_root());
- }
-
- if($email_verify) {
- goaway(z_root());
- }
-
- authenticate_success($result['account'],true,false,true);
-
- $new_channel = false;
- $next_page = 'new_channel';
-
- if(get_config('system','auto_channel_create') || UNO) {
- $new_channel = auto_channel_create($result['account']['account_id']);
- if($new_channel['success']) {
- $channel_id = $new_channel['channel']['channel_id'];
- change_channel($channel_id);
- $next_page = '~';
- }
- else
- $new_channel = false;
- }
-
- $x = get_config('system','workflow_register_next');
- if($x) {
- $next_page = $x;
- $_SESSION['workflow'] = true;
- }
-
- goaway(z_root() . '/' . $next_page);
-
-}
-
-
-
-function register_content(&$a) {
-
- $registration_is = '';
- $other_sites = '';
-
- if(get_config('system','register_policy') == REGISTER_CLOSED) {
- if(get_config('system','directory_mode') == DIRECTORY_MODE_STANDALONE) {
- notice( t('Registration on this hub is disabled.') . EOL);
- return;
- }
-
- require_once('mod/pubsites.php');
- return pubsites_content($a);
- }
-
- if(get_config('system','register_policy') == REGISTER_APPROVE) {
- $registration_is = t('Registration on this hub is by approval only.');
- $other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>');
- }
-
- $max_dailies = intval(get_config('system','max_daily_registrations'));
- if($max_dailies) {
- $r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s",
- db_utcnow(), db_quoteinterval('1 day')
- );
- if($r && $r[0]['total'] >= $max_dailies) {
- logger('max daily registrations exceeded.');
- notice( t('This site has exceeded the number of allowed daily account registrations. Please try again tomorrow.') . EOL);
- return;
- }
- }
-
- // Configurable terms of service link
-
- $tosurl = get_config('system','tos_url');
- if(! $tosurl)
- $tosurl = z_root() . '/help/TermsOfService';
-
- $toslink = '<a href="' . $tosurl . '" target="_blank">' . t('Terms of Service') . '</a>';
-
- // Configurable whether to restrict age or not - default is based on international legal requirements
- // This can be relaxed if you are on a restricted server that does not share with public servers
-
- if(get_config('system','no_age_restriction'))
- $label_tos = sprintf( t('I accept the %s for this website'), $toslink);
- else
- $label_tos = sprintf( t('I am over 13 years of age and accept the %s for this website'), $toslink);
-
- $enable_tos = 1 - intval(get_config('system','no_termsofservice'));
-
- $email = array('email', t('Your email address'), ((x($_REQUEST,'email')) ? strip_tags(trim($_REQUEST['email'])) : ""));
- $password = array('password', t('Choose a password'), ((x($_REQUEST,'password')) ? trim($_REQUEST['password']) : ""));
- $password2 = array('password2', t('Please re-enter your password'), ((x($_REQUEST,'password2')) ? trim($_REQUEST['password2']) : ""));
- $invite_code = array('invite_code', t('Please enter your invitation code'), ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : ""));
- $name = array('name', t('Name or caption'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"'));
- $nickhub = '@' . str_replace(array('http://','https://','/'), '', get_config('system','baseurl'));
- $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub));
- $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());
- $tos = array('tos', $label_tos, '', '', array(t('no'),t('yes')));
-
- $auto_create = ((UNO) || (get_config('system','auto_channel_create')) ? true : false);
- $default_role = ((UNO) ? 'social' : get_config('system','default_permissions_role'));
-
- require_once('include/bbcode.php');
-
- $o = replace_macros(get_markup_template('register.tpl'), array(
-
- '$title' => t('Registration'),
- '$reg_is' => $registration_is,
- '$registertext' => bbcode(get_config('system','register_text')),
- '$other_sites' => $other_sites,
- '$invitations' => get_config('system','invitation_only'),
- '$invite_desc' => t('Membership on this site is by invitation only.'),
- '$invite_code' => $invite_code,
- '$auto_create' => $auto_create,
- '$name' => $name,
- '$role' => $role,
- '$default_role' => $default_role,
- '$nickname' => $nickname,
- '$enable_tos' => $enable_tos,
- '$tos' => $tos,
- '$email' => $email,
- '$pass1' => $password,
- '$pass2' => $password2,
- '$submit' => ((UNO || $auto_create || $registration_is) ? t('Register') : t('Proceed to create your first channel'))
- ));
-
- return $o;
-
-}
-
diff --git a/mod/regmod.php b/mod/regmod.php
deleted file mode 100644
index d500de0dc..000000000
--- a/mod/regmod.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-
-function regmod_content(&$a) {
-
- global $lang;
-
- $_SESSION['return_url'] = App::$cmd;
-
- if(! local_channel()) {
- info( t('Please login.') . EOL);
- $o .= '<br /><br />' . login((App::$config['system']['register_policy'] == REGISTER_CLOSED) ? 0 : 1);
- return $o;
- }
-
- if(! is_site_admin()) {
- notice( t('Permission denied.') . EOL);
- return '';
- }
-
- if(argc() != 3)
- killme();
-
- $cmd = argv(1);
- $hash = argv(2);
-
- if($cmd === 'deny') {
- if (! account_deny($hash)) killme();
- }
-
- if($cmd === 'allow') {
- if (! account_allow($hash)) killme();
- }
-}
diff --git a/mod/regver.php b/mod/regver.php
deleted file mode 100644
index a26843376..000000000
--- a/mod/regver.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-function regver_content(&$a) {
-
- global $lang;
-
- $_SESSION['return_url'] = App::$cmd;
-
- if(argc() != 3)
- killme();
-
- $cmd = argv(1);
- $hash = argv(2);
-
- if($cmd === 'deny') {
- if (! account_deny($hash)) killme();
- }
-
- if($cmd === 'allow') {
- if (! account_approve($hash)) killme();
- }
-}
diff --git a/mod/removeaccount.php b/mod/removeaccount.php
deleted file mode 100644
index b4c2bad33..000000000
--- a/mod/removeaccount.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-function removeaccount_post(&$a) {
-
- if(! local_channel())
- return;
-
- if($_SESSION['delegate'])
- return;
-
- if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password']))))
- return;
-
- if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify']))))
- return;
-
- if($_POST['verify'] !== $_SESSION['remove_account_verify'])
- return;
-
-
- $account = App::get_account();
- $account_id = get_account_id();
-
- if(! account_verify_password($account['account_email'],$_POST['qxz_password']))
- return;
-
- if($account['account_password_changed'] != NULL_DATE) {
- $d1 = datetime_convert('UTC','UTC','now - 48 hours');
- if($account['account_password_changed'] > d1) {
- notice( t('Account removals are not allowed within 48 hours of changing the account password.') . EOL);
- return;
- }
- }
-
- require_once('include/Contact.php');
-
- $global_remove = intval($_POST['global']);
-
- account_remove($account_id,true);
-
-}
-
-
-
-function removeaccount_content(&$a) {
-
- if(! local_channel())
- goaway(z_root());
-
- $hash = random_string();
-
- $_SESSION['remove_account_verify'] = $hash;
- $tpl = get_markup_template('removeaccount.tpl');
- $o .= replace_macros($tpl, array(
- '$basedir' => z_root(),
- '$hash' => $hash,
- '$title' => t('Remove This Account'),
- '$desc' => array(t('WARNING: '), t('This account and all its channels will be completely removed from the network. '), t('This action is permanent and can not be undone!')),
- '$passwd' => t('Please enter your password for verification:'),
- '$global' => array('global', t('Remove this account, all its channels and all its channel clones from the network'), false, t('By default only the instances of the channels located on this hub will be removed from the network')),
- '$submit' => t('Remove Account')
- ));
-
- return $o;
-
-}
diff --git a/mod/removeme.php b/mod/removeme.php
deleted file mode 100644
index ab1d5fe4f..000000000
--- a/mod/removeme.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-function removeme_post(&$a) {
-
- if(! local_channel())
- return;
-
- if($_SESSION['delegate'])
- return;
-
- if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password']))))
- return;
-
- if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify']))))
- return;
-
- if($_POST['verify'] !== $_SESSION['remove_account_verify'])
- return;
-
-
- $account = App::get_account();
-
- if(! account_verify_password($account['account_email'],$_POST['qxz_password']))
- return;
-
- if($account['account_password_changed'] != NULL_DATE) {
- $d1 = datetime_convert('UTC','UTC','now - 48 hours');
- if($account['account_password_changed'] > d1) {
- notice( t('Channel removals are not allowed within 48 hours of changing the account password.') . EOL);
- return;
- }
- }
-
- require_once('include/Contact.php');
-
- $global_remove = intval($_POST['global']);
-
- channel_remove(local_channel(),1 - $global_remove,true);
-
-}
-
-
-
-function removeme_content(&$a) {
-
- if(! local_channel())
- goaway(z_root());
-
- $hash = random_string();
-
- $_SESSION['remove_account_verify'] = $hash;
-
- $tpl = get_markup_template('removeme.tpl');
- $o .= replace_macros($tpl, array(
- '$basedir' => z_root(),
- '$hash' => $hash,
- '$title' => t('Remove This Channel'),
- '$desc' => array(t('WARNING: '), t('This channel will be completely removed from the network. '), t('This action is permanent and can not be undone!')),
- '$passwd' => t('Please enter your password for verification:'),
- '$global' => array('global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network'), array(t('No'),t('Yes'))),
- '$submit' => t('Remove Channel')
- ));
-
- return $o;
-
-}
diff --git a/mod/rmagic.php b/mod/rmagic.php
deleted file mode 100644
index 6a47b495a..000000000
--- a/mod/rmagic.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-
-function rmagic_init(&$a) {
-
- if(local_channel())
- goaway(z_root());
-
- $me = get_my_address();
- if($me) {
- $r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1",
- dbesc($me)
- );
- if($r) {
- if($r[0]['hubloc_url'] === z_root())
- goaway(z_root() . '/login');
- $dest = z_root() . '/' . str_replace('zid=','zid_=',App::$query_string);
- goaway($r[0]['hubloc_url'] . '/magic' . '?f=&dest=' . $dest);
- }
- }
-}
-
-function rmagic_post(&$a) {
-
- $address = trim($_REQUEST['address']);
-
- if(strpos($address,'@') === false) {
- $arr = array('address' => $address);
- call_hooks('reverse_magic_auth', $arr);
-
- try {
- require_once('library/openid/openid.php');
- $openid = new LightOpenID(z_root());
- $openid->identity = $address;
- $openid->returnUrl = z_root() . '/openid';
- $openid->required = array('namePerson/friendly', 'namePerson');
- $openid->optional = array('namePerson/first','media/image/aspect11','media/image/default');
- goaway($openid->authUrl());
- } catch (Exception $e) {
- notice( t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.').'<br /><br >'. t('The error message was:').' '.$e->getMessage());
- }
-
- // if they're still here...
- notice( t('Authentication failed.') . EOL);
- return;
- }
- else {
-
- // Presumed Red identity. Perform reverse magic auth
-
- if(strpos($address,'@') === false) {
- notice('Invalid address.');
- return;
- }
-
- $r = null;
- if($address) {
- $r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1",
- dbesc($address)
- );
- }
- if($r) {
- $url = $r[0]['hubloc_url'];
- }
- else {
- $url = 'https://' . substr($address,strpos($address,'@')+1);
- }
-
- if($url) {
- if($_SESSION['return_url'])
- $dest = urlencode(z_root() . '/' . str_replace('zid=','zid_=',$_SESSION['return_url']));
- else
- $dest = urlencode(z_root() . '/' . str_replace('zid=','zid_=',App::$query_string));
-
- goaway($url . '/magic' . '?f=&dest=' . $dest);
- }
- }
-}
-
-
-function rmagic_content(&$a) {
-
- $o = replace_macros(get_markup_template('rmagic.tpl'),array(
- '$title' => t('Remote Authentication'),
- '$desc' => t('Enter your channel address (e.g. channel@example.com)'),
- '$submit' => t('Authenticate')
- ));
- return $o;
-
-} \ No newline at end of file
diff --git a/mod/rpost.php b/mod/rpost.php
deleted file mode 100644
index 3e036cac6..000000000
--- a/mod/rpost.php
+++ /dev/null
@@ -1,138 +0,0 @@
-<?php /** @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');
-require_once('include/zot.php');
-
-/**
- * remote post
- *
- * https://yoursite/rpost?f=&title=&body=&remote_return=
- *
- * This can be called via either GET or POST, use POST for long body content as suhosin often limits GET parameter length
- *
- * f= placeholder, often required
- * title= Title of post
- * body= Body of post
- * url= URL which will be parsed and the results appended to the body
- * source= Source application
- * remote_return= absolute URL to return after posting is finished
- * type= choices are 'html' or 'bbcode', default is 'bbcode'
- *
- */
-
-
-
-function rpost_content(&$a) {
-
- $o = '';
-
- if(! local_channel()) {
- if(remote_channel()) {
- // redirect to your own site.
- // We can only do this with a GET request so you'll need to keep the text short or risk getting truncated
- // by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin
- // blocks them.
-
- $url = get_rpost_path(App::get_observer());
- // make sure we're not looping to our own hub
- if(($url) && (! stristr($url, App::get_hostname()))) {
- foreach($_REQUEST as $key => $arg) {
- $url .= '&' . $key . '=' . $arg;
- }
- goaway($url);
- }
- }
-
- // The login procedure is going to bugger our $_REQUEST variables
- // so save them in the session.
-
- if(array_key_exists('body',$_REQUEST)) {
- $_SESSION['rpost'] = $_REQUEST;
- }
- return login();
- }
-
- // If we have saved rpost session variables, but nothing in the current $_REQUEST, recover the saved variables
-
- if((! array_key_exists('body',$_REQUEST)) && (array_key_exists('rpost',$_SESSION))) {
- $_REQUEST = $_SESSION['rpost'];
- unset($_SESSION['rpost']);
- }
-
- if(array_key_exists('channel',$_REQUEST)) {
- $r = q("select channel_id from channel where channel_account_id = %d and channel_address = '%s' limit 1",
- intval(get_account_id()),
- dbesc($_REQUEST['channel'])
- );
- if($r) {
- require_once('include/security.php');
- $change = change_channel($r[0]['channel_id']);
- }
- }
-
- if($_REQUEST['remote_return']) {
- $_SESSION['remote_return'] = $_REQUEST['remote_return'];
- }
- if(argc() > 1 && argv(1) === 'return') {
- if($_SESSION['remote_return'])
- goaway($_SESSION['remote_return']);
- goaway(z_root() . '/network');
- }
-
- $plaintext = true;
-// if(feature_enabled(local_channel(),'richtext'))
-// $plaintext = false;
-
- if(array_key_exists('type', $_REQUEST) && $_REQUEST['type'] === 'html') {
- require_once('include/html2bbcode.php');
- $_REQUEST['body'] = html2bbcode($_REQUEST['body']);
- }
-
- $channel = App::get_channel();
-
-
- $acl = new Zotlabs\Access\AccessList($channel);
-
- $channel_acl = $acl->get();
-
- if($_REQUEST['url']) {
- $x = z_fetch_url(z_root() . '/linkinfo?f=&url=' . urlencode($_REQUEST['url']));
- if($x['success'])
- $_REQUEST['body'] = $_REQUEST['body'] . $x['body'];
- }
-
- $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' => (($acl->is_private()) ? 'lock' : 'unlock'),
- 'acl' => populate_acl($channel_acl,true,(($channel['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : '')),
- 'bang' => '',
- 'visitor' => true,
- 'profile_uid' => local_channel(),
- 'title' => $_REQUEST['title'],
- 'body' => $_REQUEST['body'],
- 'attachment' => $_REQUEST['attachment'],
- 'source' => ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : ''),
- 'return_path' => 'rpost/return',
- 'bbco_autocomplete' => 'bbcode',
- '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;
-
-}
-
-
diff --git a/mod/rsd_xml.php b/mod/rsd_xml.php
deleted file mode 100644
index 4ce82dbe0..000000000
--- a/mod/rsd_xml.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-// What do we need this for?
-
-function rsd_xml_content(&$a) {
- header ("Content-Type: text/xml");
- echo '<?xml version="1.0" encoding="UTF-8"?>
- <rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">
- <service>
- <engineName>Red</engineName>
- <engineLink>http://friendica.com/</engineLink>
- <apis>
- <api name="Twitter" preferred="true" apiLink="'.z_root().'/api/" blogID="">
- <settings>
- <docs>http://status.net/wiki/TwitterCompatibleAPI</docs>
- <setting name="OAuth">false</setting>
- </settings>
- </api>
- </apis>
- </service>
- </rsd>
- ';
-die();
-} \ No newline at end of file
diff --git a/mod/search.php b/mod/search.php
deleted file mode 100644
index 37bd00a66..000000000
--- a/mod/search.php
+++ /dev/null
@@ -1,222 +0,0 @@
-<?php
-
-function search_init(&$a) {
- if(x($_REQUEST,'search'))
- App::$data['search'] = $_REQUEST['search'];
-}
-
-
-function search_content(&$a,$update = 0, $load = false) {
-
- if((get_config('system','block_public')) || (get_config('system','block_public_search'))) {
- if ((! local_channel()) && (! remote_channel())) {
- notice( t('Public access denied.') . EOL);
- return;
- }
- }
-
- if($load)
- $_SESSION['loadtime'] = datetime_convert();
-
- nav_set_selected('search');
-
- require_once("include/bbcode.php");
- require_once('include/security.php');
- require_once('include/conversation.php');
- require_once('include/items.php');
-
- $format = (($_REQUEST['format']) ? $_REQUEST['format'] : '');
- if($format !== '') {
- $update = $load = 1;
- }
-
- $observer = App::get_observer();
- $observer_hash = (($observer) ? $observer['xchan_hash'] : '');
-
- $o = '<div id="live-search"></div>' . "\r\n";
-
- $o = '<div class="generic-content-wrapper-styled">' . "\r\n";
-
- $o .= '<h3>' . t('Search') . '</h3>';
-
- if(x(App::$data,'search'))
- $search = trim(App::$data['search']);
- else
- $search = ((x($_GET,'search')) ? trim(rawurldecode($_GET['search'])) : '');
-
- $tag = false;
- if(x($_GET,'tag')) {
- $tag = true;
- $search = ((x($_GET,'tag')) ? trim(rawurldecode($_GET['tag'])) : '');
- }
-
- if((! local_channel()) || (! feature_enabled(local_channel(),'savedsearch')))
- $o .= search($search,'search-box','/search',((local_channel()) ? true : false));
-
- if(strpos($search,'#') === 0) {
- $tag = true;
- $search = substr($search,1);
- }
- if(strpos($search,'@') === 0) {
- $search = substr($search,1);
- goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search);
- }
- if(strpos($search,'?') === 0) {
- $search = substr($search,1);
- goaway(z_root() . '/help' . '?f=1&navsearch=1&search=' . $search);
- }
-
- // look for a naked webbie
- if(strpos($search,'@') !== false) {
- goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search);
- }
-
- if(! $search)
- return $o;
-
- if($tag) {
- $sql_extra = sprintf(" AND `item`.`id` IN (select `oid` from term where otype = %d and type in ( %d , %d) and term = '%s') ",
- intval(TERM_OBJ_POST),
- intval(TERM_HASHTAG),
- intval(TERM_COMMUNITYTAG),
- dbesc(protect_sprintf($search))
- );
- }
- else {
- $regstr = db_getfunc('REGEXP');
- $sql_extra = sprintf(" AND `item`.`body` $regstr '%s' ", dbesc(protect_sprintf(preg_quote($search))));
- }
-
- // Here is the way permissions work in the search module...
- // Only public posts can be shown
- // OR your own posts if you are a logged in member
- // No items will be shown if the member has a blocked profile wall.
-
- 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.
-
- $o .= '<div id="live-search"></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' => 'search',
- '$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',
- '$fh' => '0',
- '$nouveau' => '0',
- '$wall' => '0',
- '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
- '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
- '$search' => (($tag) ? urlencode('#') : '') . $search,
- '$order' => '',
- '$file' => '',
- '$cats' => '',
- '$tags' => '',
- '$mid' => '',
- '$verb' => '',
- '$dend' => '',
- '$dbegin' => ''
- ));
-
-
- }
-
- $item_normal = item_normal();
- $pub_sql = public_permissions_sql($observer_hash);
-
- require_once('include/identity.php');
-
- $sys = get_sys_channel();
-
- if(($update) && ($load)) {
- $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']));
-
- // in case somebody turned off public access to sys channel content with permissions
-
- if(! perm_is_allowed($sys['channel_id'],$observer_hash,'view_stream'))
- $sys['xchan_hash'] .= 'disabled';
-
- if($load) {
- $r = null;
-
- if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
- $prefix = 'distinct on (created, mid)';
- $suffix = 'ORDER BY created DESC, mid';
- } else {
- $prefix = 'distinct';
- $suffix = 'group by mid ORDER BY created DESC';
- }
- if(local_channel()) {
- $r = q("SELECT $prefix mid, item.id as item_id, item.* from item
- WHERE ((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' AND item_private = 0 )
- OR ( `item`.`uid` = %d )) OR item.owner_xchan = '%s' )
- $item_normal
- $sql_extra
- $suffix $pager_sql ",
- intval(local_channel()),
- dbesc($sys['xchan_hash'])
- );
- }
- if($r === null) {
- $r = q("SELECT $prefix mid, item.id as item_id, item.* from item
- WHERE (((( `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) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
- $pub_sql ) OR owner_xchan = '%s')
- $item_normal
- $sql_extra
- $suffix $pager_sql",
- dbesc($sys['xchan_hash'])
- );
- }
- }
- else {
- $r = array();
- }
- }
-
- if($r) {
- xchan_query($r);
- $items = fetch_post_tags($r,true);
- } else {
- $items = array();
- }
-
-
- if($format == 'json') {
- $result = array();
- require_once('include/conversation.php');
- foreach($items as $item) {
- $item['html'] = bbcode($item['body']);
- $x = encode_item($item);
- $x['html'] = prepare_text($item['body'],$item['mimetype']);
- $result[] = $x;
- }
- json_return_and_die(array('success' => true,'messages' => $result));
- }
-
- if($tag)
- $o .= '<h2>' . sprintf( t('Items tagged with: %s'),htmlspecialchars($search, ENT_COMPAT,'UTF-8')) . '</h2>';
- else
- $o .= '<h2>' . sprintf( t('Search results for: %s'),htmlspecialchars($search, ENT_COMPAT,'UTF-8')) . '</h2>';
-
- $o .= conversation($a,$items,'search',$update,'client');
-
- $o .= '</div>';
-
- return $o;
-}
-
diff --git a/mod/search_ac.php b/mod/search_ac.php
deleted file mode 100644
index 6ffdc6ed5..000000000
--- a/mod/search_ac.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-// Autocomplete for saved searches. Should probably be put in the same place as the other autocompletes
-function search_ac_init(&$a){
- if(!local_channel())
- killme();
-
-
- $start = (x($_REQUEST,'start')?$_REQUEST['start']:0);
- $count = (x($_REQUEST,'count')?$_REQUEST['count']:100);
- $search = (x($_REQUEST,'search')?$_REQUEST['search']:"");
-
- if(x($_REQUEST,'query') && strlen($_REQUEST['query'])) {
- $search = $_REQUEST['query'];
- }
-
- // Priority to people searches
-
- if ($search) {
- $people_sql_extra = protect_sprintf(" AND `xchan_name` LIKE '%". dbesc($search) . "%' ");
- $tag_sql_extra = protect_sprintf(" AND term LIKE '%". dbesc($search) . "%' ");
- }
-
-
- $r = q("SELECT `abook_id`, `xchan_name`, `xchan_photo_s`, `xchan_url`, `xchan_addr` FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d
- $people_sql_extra
- ORDER BY `xchan_name` ASC ",
- intval(local_channel())
- );
-
- $results = array();
- if($r) {
- foreach($r as $g) {
- $results[] = array(
- "photo" => $g['xchan_photo_s'],
- "name" => '@'.$g['xchan_name'],
- "id" => $g['abook_id'],
- "link" => $g['xchan_url'],
- "label" => '',
- "nick" => '',
- );
- }
- }
-
- $r = q("select distinct term, tid, url from term where type in ( %d, %d ) $tag_sql_extra group by term order by term asc",
- intval(TERM_HASHTAG),
- intval(TERM_COMMUNITYTAG)
- );
-
- if(count($r)) {
- foreach($r as $g) {
- $results[] = array(
- "photo" => z_root() . '/images/hashtag.png',
- "name" => '#'.$g['term'],
- "id" => $g['tid'],
- "link" => $g['url'],
- "label" => '',
- "nick" => '',
- );
- }
- }
-
- header("content-type: application/json");
- $o = array(
- 'start' => $start,
- 'count' => $count,
- 'items' => $results,
- );
- echo json_encode($o);
-
- logger('search_ac: ' . print_r($x,true));
-
- killme();
-}
-
-
diff --git a/mod/service_limits.php b/mod/service_limits.php
deleted file mode 100644
index 8ce410ab6..000000000
--- a/mod/service_limits.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php /** @file */
-
-
-function service_limits_content(&$a) {
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- $account = App::get_account();
- if($account['account_service_class']) {
- $x = get_config('service_class',$account['account_service_class']);
- if($x) {
- $o = print_r($x,true);
- return $o;
- }
- }
- return t('No service class restrictions found.');
-}
-
-
- \ No newline at end of file
diff --git a/mod/settings.php b/mod/settings.php
deleted file mode 100644
index dbb381191..000000000
--- a/mod/settings.php
+++ /dev/null
@@ -1,1144 +0,0 @@
-<?php /** @file */
-
-require_once('include/zot.php');
-
-function get_theme_config_file($theme){
-
- $base_theme = App::$theme_info['extends'];
-
- if (file_exists("view/theme/$theme/php/config.php")){
- return "view/theme/$theme/php/config.php";
- }
- if (file_exists("view/theme/$base_theme/php/config.php")){
- return "view/theme/$base_theme/php/config.php";
- }
- return null;
-}
-
-function settings_init(&$a) {
- if(! local_channel())
- return;
-
- if($_SESSION['delegate'])
- return;
-
- App::$profile_uid = local_channel();
-
- // default is channel settings in the absence of other arguments
-
- if(argc() == 1) {
- // We are setting these values - don't use the argc(), argv() functions here
- App::$argc = 2;
- App::$argv[] = 'channel';
- }
-
-
-
-}
-
-
-function settings_post(&$a) {
-
- if(! local_channel())
- return;
-
- if($_SESSION['delegate'])
- return;
-
- $channel = App::get_channel();
-
- logger('mod_settings: ' . print_r($_REQUEST,true));
-
-
- if((argc() > 1) && (argv(1) === 'oauth') && x($_POST,'remove')){
- check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
-
- $key = $_POST['remove'];
- q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
- dbesc($key),
- local_channel());
- goaway(z_root()."/settings/oauth/");
- return;
- }
-
- if((argc() > 2) && (argv(1) === 'oauth') && (argv(2) === 'edit'||(argv(2) === 'add')) && x($_POST,'submit')) {
-
- check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
-
- $name = ((x($_POST,'name')) ? $_POST['name'] : '');
- $key = ((x($_POST,'key')) ? $_POST['key'] : '');
- $secret = ((x($_POST,'secret')) ? $_POST['secret'] : '');
- $redirect = ((x($_POST,'redirect')) ? $_POST['redirect'] : '');
- $icon = ((x($_POST,'icon')) ? $_POST['icon'] : '');
- $ok = true;
- if($name == '') {
- $ok = false;
- notice( t('Name is required') . EOL);
- }
- if($key == '' || $secret == '') {
- $ok = false;
- notice( t('Key and Secret are required') . EOL);
- }
-
- if($ok) {
- if ($_POST['submit']==t("Update")){
- $r = q("UPDATE clients SET
- client_id='%s',
- pw='%s',
- name='%s',
- redirect_uri='%s',
- icon='%s',
- uid=%d
- WHERE client_id='%s'",
- dbesc($key),
- dbesc($secret),
- dbesc($name),
- dbesc($redirect),
- dbesc($icon),
- intval(local_channel()),
- dbesc($key));
- } else {
- $r = q("INSERT INTO clients (client_id, pw, name, redirect_uri, icon, uid)
- VALUES ('%s','%s','%s','%s','%s',%d)",
- dbesc($key),
- dbesc($secret),
- dbesc($name),
- dbesc($redirect),
- dbesc($icon),
- intval(local_channel())
- );
- $r = q("INSERT INTO xperm (xp_client, xp_channel, xp_perm) VALUES ('%s', %d, '%s') ",
- dbesc($key),
- intval(local_channel()),
- dbesc('all')
- );
- }
- }
- goaway(z_root()."/settings/oauth/");
- return;
- }
-
- if((argc() > 1) && (argv(1) == 'featured')) {
- check_form_security_token_redirectOnErr('/settings/featured', 'settings_featured');
-
- call_hooks('feature_settings_post', $_POST);
-
- build_sync_packet();
- return;
- }
-
-
-
- if((argc() > 1) && (argv(1) === 'features')) {
- check_form_security_token_redirectOnErr('/settings/features', 'settings_features');
-
- // Build list of features and check which are set
- $features = get_features();
- $all_features = array();
- foreach($features as $k => $v) {
- foreach($v as $f)
- $all_features[] = $f[0];
- }
- foreach($all_features as $k) {
- if(x($_POST,"feature_$k"))
- set_pconfig(local_channel(),'feature',$k, 1);
- else
- set_pconfig(local_channel(),'feature',$k, 0);
- }
- build_sync_packet();
- return;
- }
-
- if((argc() > 1) && (argv(1) == 'display')) {
-
- check_form_security_token_redirectOnErr('/settings/display', 'settings_display');
-
- $theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : App::$channel['channel_theme']);
- $mobile_theme = ((x($_POST,'mobile_theme')) ? notags(trim($_POST['mobile_theme'])) : '');
- $preload_images = ((x($_POST,'preload_images')) ? intval($_POST['preload_images']) : 0);
- $user_scalable = ((x($_POST,'user_scalable')) ? intval($_POST['user_scalable']) : 0);
- $nosmile = ((x($_POST,'nosmile')) ? intval($_POST['nosmile']) : 0);
- $title_tosource = ((x($_POST,'title_tosource')) ? intval($_POST['title_tosource']) : 0);
- $channel_list_mode = ((x($_POST,'channel_list_mode')) ? intval($_POST['channel_list_mode']) : 0);
- $network_list_mode = ((x($_POST,'network_list_mode')) ? intval($_POST['network_list_mode']) : 0);
-
- $channel_divmore_height = ((x($_POST,'channel_divmore_height')) ? intval($_POST['channel_divmore_height']) : 400);
- if($channel_divmore_height < 50)
- $channel_divmore_height = 50;
- $network_divmore_height = ((x($_POST,'network_divmore_height')) ? intval($_POST['network_divmore_height']) : 400);
- if($network_divmore_height < 50)
- $network_divmore_height = 50;
-
- $browser_update = ((x($_POST,'browser_update')) ? intval($_POST['browser_update']) : 0);
- $browser_update = $browser_update * 1000;
- if($browser_update < 10000)
- $browser_update = 10000;
-
- $itemspage = ((x($_POST,'itemspage')) ? intval($_POST['itemspage']) : 20);
- if($itemspage > 100)
- $itemspage = 100;
-
-
- if ($mobile_theme == "---")
- del_pconfig(local_channel(),'system','mobile_theme');
- else {
- set_pconfig(local_channel(),'system','mobile_theme',$mobile_theme);
- }
-
- set_pconfig(local_channel(),'system','preload_images',$preload_images);
- set_pconfig(local_channel(),'system','user_scalable',$user_scalable);
- set_pconfig(local_channel(),'system','update_interval', $browser_update);
- set_pconfig(local_channel(),'system','itemspage', $itemspage);
- set_pconfig(local_channel(),'system','no_smilies',1-intval($nosmile));
- set_pconfig(local_channel(),'system','title_tosource',$title_tosource);
- set_pconfig(local_channel(),'system','channel_list_mode', $channel_list_mode);
- set_pconfig(local_channel(),'system','network_list_mode', $network_list_mode);
- set_pconfig(local_channel(),'system','channel_divmore_height', $channel_divmore_height);
- set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height);
-
- if ($theme == App::$channel['channel_theme']){
- // call theme_post only if theme has not been changed
- if( ($themeconfigfile = get_theme_config_file($theme)) != null){
- require_once($themeconfigfile);
- theme_post($a);
- }
- }
-
- $r = q("UPDATE channel SET channel_theme = '%s' WHERE channel_id = %d",
- dbesc($theme),
- intval(local_channel())
- );
-
- call_hooks('display_settings_post', $_POST);
- build_sync_packet();
- goaway(z_root() . '/settings/display' );
- return; // NOTREACHED
- }
-
-
- if(argc() > 1 && argv(1) === 'account') {
-
- check_form_security_token_redirectOnErr('/settings/account', 'settings_account');
-
- call_hooks('account_settings_post', $_POST);
-// call_hooks('settings_account', $_POST);
-
- $errs = array();
-
- $email = ((x($_POST,'email')) ? trim(notags($_POST['email'])) : '');
- $account = App::get_account();
- if($email != $account['account_email']) {
- if(! valid_email($email))
- $errs[] = t('Not valid email.');
- $adm = trim(get_config('system','admin_email'));
- if(($adm) && (strcasecmp($email,$adm) == 0)) {
- $errs[] = t('Protected email address. Cannot change to that email.');
- $email = App::$user['email'];
- }
- if(! $errs) {
- $r = q("update account set account_email = '%s' where account_id = %d",
- dbesc($email),
- intval($account['account_id'])
- );
- if(! $r)
- $errs[] = t('System failure storing new email. Please try again.');
- }
- }
-
- if($errs) {
- foreach($errs as $err)
- notice($err . EOL);
- $errs = array();
- }
-
-
- if((x($_POST,'npassword')) || (x($_POST,'confirm'))) {
-
- $origpass = trim($_POST['origpass']);
-
- require_once('include/auth.php');
- if(! account_verify_password($email,$origpass)) {
- $errs[] = t('Password verification failed.');
- }
-
- $newpass = trim($_POST['npassword']);
- $confirm = trim($_POST['confirm']);
-
- if($newpass != $confirm ) {
- $errs[] = t('Passwords do not match. Password unchanged.');
- }
-
- if((! x($newpass)) || (! x($confirm))) {
- $errs[] = t('Empty passwords are not allowed. Password unchanged.');
- }
-
- if(! $errs) {
- $salt = random_string(32);
- $password_encoded = hash('whirlpool', $salt . $newpass);
- $r = q("update account set account_salt = '%s', account_password = '%s', account_password_changed = '%s'
- where account_id = %d",
- dbesc($salt),
- dbesc($password_encoded),
- dbesc(datetime_convert()),
- intval(get_account_id())
- );
- if($r)
- info( t('Password changed.') . EOL);
- else
- $errs[] = t('Password update failed. Please try again.');
- }
- }
-
-
- if($errs) {
- foreach($errs as $err)
- notice($err . EOL);
- }
- goaway(z_root() . '/settings/account' );
- }
-
-
- check_form_security_token_redirectOnErr('/settings', 'settings');
-
- call_hooks('settings_post', $_POST);
-
- $set_perms = '';
-
- $role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : '');
- $oldrole = get_pconfig(local_channel(),'system','permissions_role');
-
- if(($role != $oldrole) || ($role === 'custom')) {
-
- if($role === 'custom') {
- $hide_presence = (((x($_POST,'hide_presence')) && (intval($_POST['hide_presence']) == 1)) ? 1: 0);
- $publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
- $def_group = ((x($_POST,'group-selection')) ? notags(trim($_POST['group-selection'])) : '');
- $r = q("update channel set channel_default_group = '%s' where channel_id = %d",
- dbesc($def_group),
- intval(local_channel())
- );
-
- $global_perms = get_perms();
-
- foreach($global_perms as $k => $v) {
- $set_perms .= ', ' . $v[0] . ' = ' . intval($_POST[$k]) . ' ';
- }
- $acl = new Zotlabs\Access\AccessList($channel);
- $acl->set_from_array($_POST);
- $x = $acl->get();
-
- $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s',
- channel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d",
- dbesc($x['allow_cid']),
- dbesc($x['allow_gid']),
- dbesc($x['deny_cid']),
- dbesc($x['deny_gid']),
- intval(local_channel())
- );
- }
- else {
- $role_permissions = get_role_perms($_POST['permissions_role']);
- if(! $role_permissions) {
- notice('Permissions category could not be found.');
- return;
- }
- $hide_presence = 1 - (intval($role_permissions['online']));
- if($role_permissions['default_collection']) {
- $r = q("select hash from groups where uid = %d and name = '%s' limit 1",
- intval(local_channel()),
- dbesc( t('Friends') )
- );
- if(! $r) {
- require_once('include/group.php');
- group_add(local_channel(), t('Friends'));
- group_add_member(local_channel(),t('Friends'),$channel['channel_hash']);
- $r = q("select hash from groups where uid = %d and name = '%s' limit 1",
- intval(local_channel()),
- dbesc( t('Friends') )
- );
- }
- if($r) {
- q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d",
- dbesc($r[0]['hash']),
- dbesc('<' . $r[0]['hash'] . '>'),
- intval(local_channel())
- );
- }
- else {
- notice( sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL);
- return;
- }
- }
- // no default collection
- else {
- q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '',
- channel_deny_cid = '' where channel_id = %d",
- intval(local_channel())
- );
- }
-
- $r = q("update abook set abook_my_perms = %d where abook_channel = %d and abook_self = 1",
- intval((array_key_exists('perms_accept',$role_permissions)) ? $role_permissions['perms_accept'] : 0),
- intval(local_channel())
- );
- set_pconfig(local_channel(),'system','autoperms',(($role_permissions['perms_auto']) ? intval($role_permissions['perms_accept']) : 0));
-
- foreach($role_permissions as $p => $v) {
- if(strpos($p,'channel_') !== false) {
- $set_perms .= ', ' . $p . ' = ' . intval($v) . ' ';
- }
- if($p === 'directory_publish') {
- $publish = intval($v);
- }
- }
- }
-
- set_pconfig(local_channel(),'system','hide_online_status',$hide_presence);
- set_pconfig(local_channel(),'system','permissions_role',$role);
- }
-
- $username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : '');
- $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
- $defloc = ((x($_POST,'defloc')) ? notags(trim($_POST['defloc'])) : '');
- $openid = ((x($_POST,'openid_url')) ? notags(trim($_POST['openid_url'])) : '');
- $maxreq = ((x($_POST,'maxreq')) ? intval($_POST['maxreq']) : 0);
- $expire = ((x($_POST,'expire')) ? intval($_POST['expire']) : 0);
- $evdays = ((x($_POST,'evdays')) ? intval($_POST['evdays']) : 3);
- $photo_path = ((x($_POST,'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : '');
- $attach_path = ((x($_POST,'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : '');
-
- $channel_menu = ((x($_POST['channel_menu'])) ? htmlspecialchars_decode(trim($_POST['channel_menu']),ENT_QUOTES) : '');
-
- $expire_items = ((x($_POST,'expire_items')) ? intval($_POST['expire_items']) : 0);
- $expire_starred = ((x($_POST,'expire_starred')) ? intval($_POST['expire_starred']) : 0);
- $expire_photos = ((x($_POST,'expire_photos'))? intval($_POST['expire_photos']) : 0);
- $expire_network_only = ((x($_POST,'expire_network_only'))? intval($_POST['expire_network_only']) : 0);
-
- $allow_location = (((x($_POST,'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1: 0);
-
- $blocktags = (((x($_POST,'blocktags')) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted!
- $unkmail = (((x($_POST,'unkmail')) && (intval($_POST['unkmail']) == 1)) ? 1: 0);
- $cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0);
- $suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0);
-
- $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0);
- $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0);
- $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1: 0);
- $adult = (($_POST['adult'] == 1) ? 1 : 0);
-
- $cal_first_day = (((x($_POST,'first_day')) && (intval($_POST['first_day']) == 1)) ? 1: 0);
-
- $channel = App::get_channel();
- $pageflags = $channel['channel_pageflags'];
- $existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0);
- if($adult != $existing_adult)
- $pageflags = ($pageflags ^ PAGE_ADULT);
-
-
- $notify = 0;
-
- if(x($_POST,'notify1'))
- $notify += intval($_POST['notify1']);
- if(x($_POST,'notify2'))
- $notify += intval($_POST['notify2']);
- if(x($_POST,'notify3'))
- $notify += intval($_POST['notify3']);
- if(x($_POST,'notify4'))
- $notify += intval($_POST['notify4']);
- if(x($_POST,'notify5'))
- $notify += intval($_POST['notify5']);
- if(x($_POST,'notify6'))
- $notify += intval($_POST['notify6']);
- if(x($_POST,'notify7'))
- $notify += intval($_POST['notify7']);
- if(x($_POST,'notify8'))
- $notify += intval($_POST['notify8']);
-
-
- $vnotify = 0;
-
- if(x($_POST,'vnotify1'))
- $vnotify += intval($_POST['vnotify1']);
- if(x($_POST,'vnotify2'))
- $vnotify += intval($_POST['vnotify2']);
- if(x($_POST,'vnotify3'))
- $vnotify += intval($_POST['vnotify3']);
- if(x($_POST,'vnotify4'))
- $vnotify += intval($_POST['vnotify4']);
- if(x($_POST,'vnotify5'))
- $vnotify += intval($_POST['vnotify5']);
- if(x($_POST,'vnotify6'))
- $vnotify += intval($_POST['vnotify6']);
- if(x($_POST,'vnotify7'))
- $vnotify += intval($_POST['vnotify7']);
- if(x($_POST,'vnotify8'))
- $vnotify += intval($_POST['vnotify8']);
- if(x($_POST,'vnotify9'))
- $vnotify += intval($_POST['vnotify9']);
- if(x($_POST,'vnotify10'))
- $vnotify += intval($_POST['vnotify10']);
- if(x($_POST,'vnotify11'))
- $vnotify += intval($_POST['vnotify11']);
-
- $always_show_in_notices = x($_POST,'always_show_in_notices') ? 1 : 0;
-
- $channel = App::get_channel();
-
- $err = '';
-
- $name_change = false;
-
- if($username != $channel['channel_name']) {
- $name_change = true;
- require_once('include/identity.php');
- $err = validate_channelname($username);
- if($err) {
- notice($err);
- return;
- }
- }
-
- if($timezone != $channel['channel_timezone']) {
- if(strlen($timezone))
- date_default_timezone_set($timezone);
- }
-
- set_pconfig(local_channel(),'system','use_browser_location',$allow_location);
- set_pconfig(local_channel(),'system','suggestme', $suggestme);
- set_pconfig(local_channel(),'system','post_newfriend', $post_newfriend);
- set_pconfig(local_channel(),'system','post_joingroup', $post_joingroup);
- set_pconfig(local_channel(),'system','post_profilechange', $post_profilechange);
- set_pconfig(local_channel(),'system','blocktags',$blocktags);
- set_pconfig(local_channel(),'system','channel_menu',$channel_menu);
- set_pconfig(local_channel(),'system','vnotify',$vnotify);
- set_pconfig(local_channel(),'system','always_show_in_notices',$always_show_in_notices);
- set_pconfig(local_channel(),'system','evdays',$evdays);
- set_pconfig(local_channel(),'system','photo_path',$photo_path);
- set_pconfig(local_channel(),'system','attach_path',$attach_path);
- set_pconfig(local_channel(),'system','cal_first_day',$cal_first_day);
-
- $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d",
- dbesc($username),
- intval($pageflags),
- dbesc($timezone),
- dbesc($defloc),
- intval($notify),
- intval($unkmail),
- intval($maxreq),
- intval($expire),
- intval(local_channel())
- );
- if($r)
- info( t('Settings updated.') . EOL);
-
- if(! is_null($publish)) {
- $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d",
- intval($publish),
- intval(local_channel())
- );
- }
-
- if($name_change) {
- $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'",
- dbesc($username),
- dbesc(datetime_convert()),
- dbesc($channel['channel_hash'])
- );
- $r = q("update profile set name = '%s' where uid = %d and is_default = 1",
- dbesc($username),
- intval($channel['channel_id'])
- );
- }
-
- proc_run('php','include/directory.php',local_channel());
-
- build_sync_packet();
-
-
- //$_SESSION['theme'] = $theme;
- if($email_changed && App::$config['system']['register_policy'] == REGISTER_VERIFY) {
-
- // FIXME - set to un-verified, blocked and redirect to logout
- // Why? Are we verifying people or email addresses?
-
- }
-
- goaway(z_root() . '/settings' );
- return; // NOTREACHED
-}
-
-
-
-function settings_content(&$a) {
-
- $o = '';
- nav_set_selected('settings');
-
-
- if((! local_channel()) || ($_SESSION['delegate'])) {
- notice( t('Permission denied.') . EOL );
- return login();
- }
-
-
- $channel = App::get_channel();
- if($channel)
- head_set_icon($channel['xchan_photo_s']);
-
- $yes_no = array(t('No'),t('Yes'));
-
- if((argc() > 1) && (argv(1) === 'oauth')) {
-
- if((argc() > 2) && (argv(2) === 'add')) {
- $tpl = get_markup_template("settings_oauth_edit.tpl");
- $o .= replace_macros($tpl, array(
- '$form_security_token' => get_form_security_token("settings_oauth"),
- '$title' => t('Add application'),
- '$submit' => t('Submit'),
- '$cancel' => t('Cancel'),
- '$name' => array('name', t('Name'), '', t('Name of application')),
- '$key' => array('key', t('Consumer Key'), random_string(16), t('Automatically generated - change if desired. Max length 20')),
- '$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')),
- '$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')),
- '$icon' => array('icon', t('Icon url'), '', t('Optional')),
- ));
- return $o;
- }
-
- if((argc() > 3) && (argv(2) === 'edit')) {
- $r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d",
- dbesc(argv(3)),
- local_channel());
-
- if (!count($r)){
- notice(t('Application not found.'));
- return;
- }
- $app = $r[0];
-
- $tpl = get_markup_template("settings_oauth_edit.tpl");
- $o .= replace_macros($tpl, array(
- '$form_security_token' => get_form_security_token("settings_oauth"),
- '$title' => t('Add application'),
- '$submit' => t('Update'),
- '$cancel' => t('Cancel'),
- '$name' => array('name', t('Name'), $app['name'] , ''),
- '$key' => array('key', t('Consumer Key'), $app['client_id'], ''),
- '$secret' => array('secret', t('Consumer Secret'), $app['pw'], ''),
- '$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], ''),
- '$icon' => array('icon', t('Icon url'), $app['icon'], ''),
- ));
- return $o;
- }
-
- if((argc() > 3) && (argv(2) === 'delete')) {
- check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't');
-
- $r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d",
- dbesc(argv(3)),
- local_channel());
- goaway(z_root()."/settings/oauth/");
- return;
- }
-
-
- $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my
- FROM clients
- LEFT JOIN tokens ON clients.client_id=tokens.client_id
- WHERE clients.uid IN (%d,0)",
- local_channel(),
- local_channel());
-
-
- $tpl = get_markup_template("settings_oauth.tpl");
- $o .= replace_macros($tpl, array(
- '$form_security_token' => get_form_security_token("settings_oauth"),
- '$baseurl' => z_root(),
- '$title' => t('Connected Apps'),
- '$add' => t('Add application'),
- '$edit' => t('Edit'),
- '$delete' => t('Delete'),
- '$consumerkey' => t('Client key starts with'),
- '$noname' => t('No name'),
- '$remove' => t('Remove authorization'),
- '$apps' => $r,
- ));
- return $o;
-
- }
- if((argc() > 1) && (argv(1) === 'featured')) {
- $settings_addons = "";
-
- $o = '';
-
- $r = q("SELECT * FROM `hook` WHERE `hook` = 'feature_settings' ");
- if(! $r)
- $settings_addons = t('No feature settings configured');
-
- call_hooks('feature_settings', $settings_addons);
-
- $tpl = get_markup_template("settings_addons.tpl");
- $o .= replace_macros($tpl, array(
- '$form_security_token' => get_form_security_token("settings_featured"),
- '$title' => t('Feature/Addon Settings'),
- '$settings_addons' => $settings_addons
- ));
- return $o;
- }
-
-
- /*
- * ACCOUNT SETTINGS
- */
-
-
- if((argc() > 1) && (argv(1) === 'account')) {
- $account_settings = "";
-
- call_hooks('account_settings', $account_settings);
-
- $email = App::$account['account_email'];
-
-
- $tpl = get_markup_template("settings_account.tpl");
- $o .= replace_macros($tpl, array(
- '$form_security_token' => get_form_security_token("settings_account"),
- '$title' => t('Account Settings'),
- '$origpass' => array('origpass', t('Current Password'), ' ',''),
- '$password1'=> array('npassword', t('Enter New Password'), '', ''),
- '$password2'=> array('confirm', t('Confirm New Password'), '', t('Leave password fields blank unless changing')),
- '$submit' => t('Submit'),
- '$email' => array('email', t('Email Address:'), $email, ''),
- '$removeme' => t('Remove Account'),
- '$removeaccount' => t('Remove this account including all its channels'),
- '$account_settings' => $account_settings
- ));
- return $o;
- }
-
-
-
- if((argc() > 1) && (argv(1) === 'features')) {
- $arr = array();
- $features = get_features();
-
- foreach($features as $fname => $fdata) {
- $arr[$fname] = array();
- $arr[$fname][0] = $fdata[0];
- foreach(array_slice($fdata,1) as $f) {
- $arr[$fname][1][] = array('feature_' .$f[0],$f[1],((intval(feature_enabled(local_channel(),$f[0]))) ? "1" : ''),$f[2],array(t('Off'),t('On')));
- }
- }
-
- $tpl = get_markup_template("settings_features.tpl");
- $o .= replace_macros($tpl, array(
- '$form_security_token' => get_form_security_token("settings_features"),
- '$title' => t('Additional Features'),
- '$features' => $arr,
- '$submit' => t('Submit'),
- ));
-
- return $o;
- }
-
-
-
-
-
- if((argc() > 1) && (argv(1) === 'connectors')) {
-
- $settings_connectors = "";
-
- call_hooks('connector_settings', $settings_connectors);
-
- $r = null;
-
- $tpl = get_markup_template("settings_connectors.tpl");
-
- $o .= replace_macros($tpl, array(
- '$form_security_token' => get_form_security_token("settings_connectors"),
- '$title' => t('Connector Settings'),
- '$submit' => t('Submit'),
- '$settings_connectors' => $settings_connectors
- ));
-
- call_hooks('display_settings', $o);
- return $o;
- }
-
- /*
- * DISPLAY SETTINGS
- */
-
- if((argc() > 1) && (argv(1) === 'display')) {
- $default_theme = get_config('system','theme');
- if(! $default_theme)
- $default_theme = 'default';
- $default_mobile_theme = get_config('system','mobile_theme');
- if(! $mobile_default_theme)
- $mobile_default_theme = 'none';
-
- $allowed_themes_str = get_config('system','allowed_themes');
- $allowed_themes_raw = explode(',',$allowed_themes_str);
- $allowed_themes = array();
- if(count($allowed_themes_raw))
- foreach($allowed_themes_raw as $x)
- if(strlen(trim($x)) && is_dir("view/theme/$x"))
- $allowed_themes[] = trim($x);
-
-
- $themes = array();
- $files = glob('view/theme/*');
- if($allowed_themes) {
- foreach($allowed_themes as $th) {
- $f = $th;
- $is_experimental = file_exists('view/theme/' . $th . '/experimental');
- $unsupported = file_exists('view/theme/' . $th . '/unsupported');
- $is_mobile = file_exists('view/theme/' . $th . '/mobile');
- $is_library = file_exists('view/theme/'. $th . '/library');
- $mobile_themes["---"] = t("No special theme for mobile devices");
-
- if (!$is_experimental or ($is_experimental && (get_config('experimentals','exp_themes')==1 or get_config('experimentals','exp_themes')===false))){
- $theme_name = (($is_experimental) ? sprintf(t('%s - (Experimental)'), $f) : $f);
- if (! $is_library) {
- if($is_mobile) {
- $mobile_themes[$f] = $themes[$f] = $theme_name . ' (' . t('mobile') . ')';
- }
- else {
- $mobile_themes[$f] = $themes[$f] = $theme_name;
- }
- }
- }
-
- }
- }
- $theme_selected = (!x($_SESSION,'theme')? $default_theme : $_SESSION['theme']);
- $mobile_theme_selected = (!x($_SESSION,'mobile_theme')? $default_mobile_theme : $_SESSION['mobile_theme']);
-
- $preload_images = get_pconfig(local_channel(),'system','preload_images');
- $preload_images = (($preload_images===false)? '0': $preload_images); // default if not set: 0
-
- $user_scalable = get_pconfig(local_channel(),'system','user_scalable');
- $user_scalable = (($user_scalable===false)? '1': $user_scalable); // default if not set: 1
-
- $browser_update = intval(get_pconfig(local_channel(), 'system','update_interval'));
- $browser_update = (($browser_update == 0) ? 80 : $browser_update / 1000); // default if not set: 40 seconds
-
- $itemspage = intval(get_pconfig(local_channel(), 'system','itemspage'));
- $itemspage = (($itemspage > 0 && $itemspage < 101) ? $itemspage : 20); // default if not set: 20 items
-
- $nosmile = get_pconfig(local_channel(),'system','no_smilies');
- $nosmile = (($nosmile===false)? '0': $nosmile); // default if not set: 0
-
- $title_tosource = get_pconfig(local_channel(),'system','title_tosource');
- $title_tosource = (($title_tosource===false)? '0': $title_tosource); // default if not set: 0
-
- $theme_config = "";
- if( ($themeconfigfile = get_theme_config_file($theme_selected)) != null){
- require_once($themeconfigfile);
- $theme_config = theme_content($a);
- }
-
- $tpl = get_markup_template("settings_display.tpl");
- $o = replace_macros($tpl, array(
- '$ptitle' => t('Display Settings'),
- '$d_tset' => t('Theme Settings'),
- '$d_ctset' => t('Custom Theme Settings'),
- '$d_cset' => t('Content Settings'),
- '$form_security_token' => get_form_security_token("settings_display"),
- '$submit' => t('Submit'),
- '$baseurl' => z_root(),
- '$uid' => local_channel(),
-
- '$theme' => (($themes) ? array('theme', t('Display Theme:'), $theme_selected, '', $themes, 'preview') : false),
- '$mobile_theme' => (($mobile_themes) ? array('mobile_theme', t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, '') : false),
- '$preload_images' => array('preload_images', t("Preload images before rendering the page"), $preload_images, t("The subjective page load time will be longer but the page will be ready when displayed"), $yes_no),
- '$user_scalable' => array('user_scalable', t("Enable user zoom on mobile devices"), $user_scalable, '', $yes_no),
- '$ajaxint' => array('browser_update', t("Update browser every xx seconds"), $browser_update, t('Minimum of 10 seconds, no maximum')),
- '$itemspage' => array('itemspage', t("Maximum number of conversations to load at any time:"), $itemspage, t('Maximum of 100 items')),
- '$nosmile' => array('nosmile', t("Show emoticons (smilies) as images"), 1-intval($nosmile), '', $yes_no),
- '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no),
- '$layout_editor' => t('System Page Layout Editor - (advanced)'),
- '$theme_config' => $theme_config,
- '$expert' => feature_enabled(local_channel(),'expert'),
- '$channel_list_mode' => array('channel_list_mode', t('Use blog/list mode on channel page'), get_pconfig(local_channel(),'system','channel_list_mode'), t('(comments displayed separately)'), $yes_no),
- '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on grid page'), get_pconfig(local_channel(),'system','network_list_mode'), t('(comments displayed separately)'), $yes_no),
- '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','channel_divmore_height')) ? get_pconfig(local_channel(),'system','channel_divmore_height') : 400), t('click to expand content exceeding this height')),
- '$network_divmore_height' => array('network_divmore_height', t('Grid page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','network_divmore_height')) ? get_pconfig(local_channel(),'system','network_divmore_height') : 400) , t('click to expand content exceeding this height')),
-
-
- ));
-
- return $o;
- }
-
-
-
-
-
- if(argv(1) === 'channel') {
-
- require_once('include/acl_selectors.php');
- require_once('include/permissions.php');
-
-
- $p = q("SELECT * FROM `profile` WHERE `is_default` = 1 AND `uid` = %d LIMIT 1",
- intval(local_channel())
- );
- if(count($p))
- $profile = $p[0];
-
- load_pconfig(local_channel(),'expire');
-
- $channel = App::get_channel();
-
-
- $global_perms = get_perms();
-
- $permiss = array();
-
- $perm_opts = array(
- array( t('Nobody except yourself'), 0),
- array( t('Only those you specifically allow'), PERMS_SPECIFIC),
- array( t('Approved connections'), PERMS_CONTACTS),
- array( t('Any connections'), PERMS_PENDING),
- array( t('Anybody on this website'), PERMS_SITE),
- array( t('Anybody in this network'), PERMS_NETWORK),
- array( t('Anybody authenticated'), PERMS_AUTHED),
- array( t('Anybody on the internet'), PERMS_PUBLIC)
- );
-
-
- foreach($global_perms as $k => $perm) {
- $options = array();
- foreach($perm_opts as $opt) {
- if((! $perm[2]) && $opt[1] == PERMS_PUBLIC)
- continue;
- $options[$opt[1]] = $opt[0];
- }
- $permiss[] = array($k,$perm[3],$channel[$perm[0]],$perm[4],$options);
- }
-
-
-// logger('permiss: ' . print_r($permiss,true));
-
-
-
- $username = $channel['channel_name'];
- $nickname = $channel['channel_address'];
- $timezone = $channel['channel_timezone'];
- $notify = $channel['channel_notifyflags'];
- $defloc = $channel['channel_location'];
-
- $maxreq = $channel['channel_max_friend_req'];
- $expire = $channel['channel_expire_days'];
- $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT);
- $sys_expire = get_config('system','default_expire_days');
-
-// $unkmail = App::$user['unkmail'];
-// $cntunkmail = App::$user['cntunkmail'];
-
- $hide_presence = intval(get_pconfig(local_channel(), 'system','hide_online_status'));
-
-
- $expire_items = get_pconfig(local_channel(), 'expire','items');
- $expire_items = (($expire_items===false)? '1' : $expire_items); // default if not set: 1
-
- $expire_notes = get_pconfig(local_channel(), 'expire','notes');
- $expire_notes = (($expire_notes===false)? '1' : $expire_notes); // default if not set: 1
-
- $expire_starred = get_pconfig(local_channel(), 'expire','starred');
- $expire_starred = (($expire_starred===false)? '1' : $expire_starred); // default if not set: 1
-
- $expire_photos = get_pconfig(local_channel(), 'expire','photos');
- $expire_photos = (($expire_photos===false)? '0' : $expire_photos); // default if not set: 0
-
- $expire_network_only = get_pconfig(local_channel(), 'expire','network_only');
- $expire_network_only = (($expire_network_only===false)? '0' : $expire_network_only); // default if not set: 0
-
-
- $suggestme = get_pconfig(local_channel(), 'system','suggestme');
- $suggestme = (($suggestme===false)? '0': $suggestme); // default if not set: 0
-
- $post_newfriend = get_pconfig(local_channel(), 'system','post_newfriend');
- $post_newfriend = (($post_newfriend===false)? '0': $post_newfriend); // default if not set: 0
-
- $post_joingroup = get_pconfig(local_channel(), 'system','post_joingroup');
- $post_joingroup = (($post_joingroup===false)? '0': $post_joingroup); // default if not set: 0
-
- $post_profilechange = get_pconfig(local_channel(), 'system','post_profilechange');
- $post_profilechange = (($post_profilechange===false)? '0': $post_profilechange); // default if not set: 0
-
- $blocktags = get_pconfig(local_channel(),'system','blocktags');
- $blocktags = (($blocktags===false) ? '0' : $blocktags);
-
- $timezone = date_default_timezone_get();
-
- $opt_tpl = get_markup_template("field_checkbox.tpl");
- if(get_config('system','publish_all')) {
- $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
- }
- else {
- $profile_in_dir = replace_macros($opt_tpl,array(
- '$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', $yes_no),
- ));
- }
-
- $suggestme = replace_macros($opt_tpl,array(
- '$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', $yes_no),
-
- ));
-
- $subdir = ((strlen(App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
-
- $tpl_addr = get_markup_template("settings_nick_set.tpl");
-
- $prof_addr = replace_macros($tpl_addr,array(
- '$desc' => t('Your channel address is'),
- '$nickname' => $nickname,
- '$subdir' => $subdir,
- '$basepath' => App::get_hostname()
- ));
-
- $stpl = get_markup_template('settings.tpl');
-
- $acl = new Zotlabs\Access\AccessList($channel);
- $perm_defaults = $acl->get();
-
- require_once('include/group.php');
- $group_select = mini_group_select(local_channel(),$channel['channel_default_group']);
-
- require_once('include/menu.php');
- $m1 = menu_list(local_channel());
- $menu = false;
- if($m1) {
- $menu = array();
- $current = get_pconfig(local_channel(),'system','channel_menu');
- $menu[] = array('name' => '', 'selected' => ((! $current) ? true : false));
- foreach($m1 as $m) {
- $menu[] = array('name' => htmlspecialchars($m['menu_name'],ENT_COMPAT,'UTF-8'), 'selected' => (($m['menu_name'] === $current) ? ' selected="selected" ' : false));
- }
- }
-
- $evdays = get_pconfig(local_channel(),'system','evdays');
- if(! $evdays)
- $evdays = 3;
-
- $permissions_role = get_pconfig(local_channel(),'system','permissions_role');
- if(! $permissions_role)
- $permissions_role = 'custom';
-
- $permissions_set = (($permissions_role != 'custom') ? true : false);
-
- $vnotify = get_pconfig(local_channel(),'system','vnotify');
- $always_show_in_notices = get_pconfig(local_channel(),'system','always_show_in_notices');
- if($vnotify === false)
- $vnotify = (-1);
-
- $o .= replace_macros($stpl,array(
- '$ptitle' => t('Channel Settings'),
-
- '$submit' => t('Submit'),
- '$baseurl' => z_root(),
- '$uid' => local_channel(),
- '$form_security_token' => get_form_security_token("settings"),
- '$nickname_block' => $prof_addr,
- '$h_basic' => t('Basic Settings'),
- '$username' => array('username', t('Full Name:'), $username,''),
- '$email' => array('email', t('Email Address:'), $email, ''),
- '$timezone' => array('timezone_select' , t('Your Timezone:'), $timezone, '', get_timezones()),
- '$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')),
- '$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), '', $yes_no),
-
- '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no),
-
- '$h_prv' => t('Security and Privacy Settings'),
- '$permissions_set' => $permissions_set,
- '$server_role' => Zotlabs\Project\System::get_server_role(),
- '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'),
-
- '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no),
-
- '$lbl_pmacro' => t('Simple Privacy Settings:'),
- '$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'),
- '$pmacro2' => t('Typical - <em>default public, privacy when desired (similar to social network permissions but with improved privacy)</em>'),
- '$pmacro1' => t('Private - <em>default private, never open or public</em>'),
- '$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'),
- '$permiss_arr' => $permiss,
- '$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no),
-
- '$lbl_p2macro' => t('Advanced Privacy Settings'),
-
- '$expire' => array('expire',t('Expire other channel content after this many days'),$expire,sprintf( t('0 or blank to use the website limit. The website expires after %d days.'),intval($sys_expire))),
- '$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']) , t('May reduce spam activity')),
- '$permissions' => t('Default Post Permissions'),
- '$permdesc' => t("\x28click to open/close\x29"),
- '$aclselect' => populate_acl($perm_defaults,false),
- '$suggestme' => $suggestme,
- '$group_select' => $group_select,
- '$role' => array('permissions_role' , t('Channel permissions category:'), $permissions_role, '', get_roles()),
-
- '$profile_in_dir' => $profile_in_dir,
- '$hide_friends' => $hide_friends,
- '$hide_wall' => $hide_wall,
- '$unkmail' => $unkmail,
- '$cntunkmail' => array('cntunkmail', t('Maximum private messages per day from unknown people:'), intval($channel['channel_max_anon_mail']) ,t("Useful to reduce spamming")),
-
-
- '$h_not' => t('Notification Settings'),
- '$activity_options' => t('By default post a status message when:'),
- '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no),
- '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no),
- '$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no),
- '$lbl_not' => t('Send a notification email when:'),
- '$notify1' => array('notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no),
- '$notify2' => array('notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no),
- '$notify3' => array('notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no),
- '$notify4' => array('notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no),
- '$notify5' => array('notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no),
- '$notify6' => array('notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no),
- '$notify7' => array('notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no),
- '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no),
-
-
- '$lbl_vnot' => t('Show visual notifications including:'),
-
- '$vnotify1' => array('vnotify1', t('Unseen grid activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no),
- '$vnotify2' => array('vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no),
- '$vnotify3' => array('vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no),
- '$vnotify4' => array('vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no),
- '$vnotify5' => array('vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no),
- '$vnotify6' => array('vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no),
- '$vnotify7' => array('vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no),
- '$vnotify8' => array('vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no),
- '$vnotify9' => array('vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no),
- '$vnotify10' => array('vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no),
- '$vnotify11' => array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no),
- '$always_show_in_notices' => array('always_show_in_notices', t('Also show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no),
-
- '$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')),
-
- '$h_advn' => t('Advanced Account/Page Type Settings'),
- '$h_descadvn' => t('Change the behaviour of this account for special situations'),
- '$pagetype' => $pagetype,
- '$expert' => feature_enabled(local_channel(),'expert'),
- '$hint' => t('Please enable expert mode (in <a href="settings/features">Settings > Additional features</a>) to adjust!'),
- '$lbl_misc' => t('Miscellaneous Settings'),
- '$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')),
- '$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')),
- '$menus' => $menu,
- '$menu_desc' => t('Personal menu to display in your channel pages'),
- '$removeme' => t('Remove Channel'),
- '$removechannel' => t('Remove this channel.'),
- '$firefoxshare' => t('Firefox Share $Projectname provider'),
- '$cal_first_day' => array('first_day', t('Start calendar week on monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no),
- ));
-
- call_hooks('settings_form',$o);
-
- $o .= '</form>' . "\r\n";
-
- return $o;
- }
-}
-
diff --git a/mod/setup.php b/mod/setup.php
deleted file mode 100755
index 5dccc1711..000000000
--- a/mod/setup.php
+++ /dev/null
@@ -1,744 +0,0 @@
-<?php
-/**
- * @file mod/setup.php
- *
- * Controller for the initial setup/installation.
- *
- * @todo This setup module could need some love and improvements.
- */
-
-$install_wizard_pass = 1;
-
-/**
- * @brief Initialisation for the setup module.
- *
- * @param[in,out] App &$a
- */
-function setup_init(&$a) {
-
- // Ensure that if somebody hasn't read the install documentation and doesn't have all
- // the required modules or has a totally borked shared hosting provider and they can't
- // figure out what the hell is going on - that we at least spit out an error message which
- // we can inquire about when they write to tell us that our software doesn't work.
-
- // The worst thing we can do at this point is throw a white screen of death and rely on
- // them knowing about servers and php modules and logfiles enough so that we can guess
- // at the source of the problem. As ugly as it may be, we need to throw a technically worded
- // PHP error message in their face. Once installation is complete application errors will
- // throw a white screen because these error messages divulge information which can
- // potentially be useful to hackers.
-
- error_reporting(E_ERROR | E_WARNING | E_PARSE );
- ini_set('log_errors', '0');
- ini_set('display_errors', '1');
-
- // $baseurl/setup/testrwrite to test if rewite in .htaccess is working
- if (argc() == 2 && argv(1) == "testrewrite") {
- echo 'ok';
- killme();
- }
-
- global $install_wizard_pass;
- if (x($_POST, 'pass'))
- $install_wizard_pass = intval($_POST['pass']);
- else
- $install_wizard_pass = 1;
-
-}
-
-/**
- * @brief Handle the actions of the different setup steps.
- *
- * @param[in,out] App &$a
- */
-function setup_post(&$a) {
- global $install_wizard_pass, $db;
-
- switch($install_wizard_pass) {
- case 1:
- case 2:
- return;
- break; // just in case return don't return :)
- case 3:
- $urlpath = App::get_path();
- $dbhost = trim($_POST['dbhost']);
- $dbport = intval(trim($_POST['dbport']));
- $dbuser = trim($_POST['dbuser']);
- $dbpass = trim($_POST['dbpass']);
- $dbdata = trim($_POST['dbdata']);
- $dbtype = intval(trim($_POST['dbtype']));
- $phpath = trim($_POST['phpath']);
- $adminmail = trim($_POST['adminmail']);
- $siteurl = trim($_POST['siteurl']);
- $advanced = ((intval($_POST['advanced'])) ? 1 : 0);
-
- // $siteurl should not have a trailing slash
-
- $siteurl = rtrim($siteurl,'/');
-
- require_once('include/dba/dba_driver.php');
- unset($db);
- $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true);
-
- if(! $db->connected) {
- echo 'Database Connect failed: ' . $db->error;
- killme();
- App::$data['db_conn_failed']=true;
- }
- /*if(get_db_errno()) {
- unset($db);
- $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, '', true);
-
- if(! get_db_errno()) {
- $r = q("CREATE DATABASE '%s'",
- dbesc($dbdata)
- );
- if($r) {
- unset($db);
- $db = new dba($dbhost, $dbport, $dbuser, $dbpass, $dbdata, true);
- } else {
- App::$data['db_create_failed']=true;
- }
- } else {
- App::$data['db_conn_failed']=true;
- return;
- }
- }*/
- //if(get_db_errno()) {
-
- //}
-
- return;
- break;
- case 4:
- $urlpath = App::get_path();
- $dbhost = notags(trim($_POST['dbhost']));
- $dbport = intval(notags(trim($_POST['dbport'])));
- $dbuser = notags(trim($_POST['dbuser']));
- $dbpass = notags(trim($_POST['dbpass']));
- $dbdata = notags(trim($_POST['dbdata']));
- $dbtype = intval(notags(trim($_POST['dbtype'])));
- $phpath = notags(trim($_POST['phpath']));
- $timezone = notags(trim($_POST['timezone']));
- $adminmail = notags(trim($_POST['adminmail']));
- $siteurl = notags(trim($_POST['siteurl']));
- $advanced = ((intval($_POST['advanced'])) ? 1 : 0);
-
- if($siteurl != z_root()) {
- $test = z_fetch_url($siteurl."/setup/testrewrite");
- if((! $test['success']) || ($test['body'] != 'ok')) {
- App::$data['url_fail'] = true;
- App::$data['url_error'] = $test['error'];
- return;
- }
- }
-
- // connect to db
- $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true);
-
- if(! $db->connected) {
- echo 'CRITICAL: DB not connected.';
- killme();
- }
-
- $tpl = get_intltext_template('htconfig.tpl');
- $txt = replace_macros($tpl,array(
- '$dbhost' => $dbhost,
- '$dbport' => $dbport,
- '$dbuser' => $dbuser,
- '$dbpass' => $dbpass,
- '$dbdata' => $dbdata,
- '$dbtype' => $dbtype,
- '$uno' => 1 - $advanced,
- '$timezone' => $timezone,
- '$siteurl' => $siteurl,
- '$site_id' => random_string(),
- '$phpath' => $phpath,
- '$adminmail' => $adminmail
- ));
-
- $result = file_put_contents('.htconfig.php', $txt);
- if(! $result) {
- App::$data['txt'] = $txt;
- }
-
- $errors = load_database($db);
-
- if($errors)
- App::$data['db_failed'] = $errors;
- else
- App::$data['db_installed'] = true;
-
- return;
- break;
- }
-}
-
-function get_db_errno() {
- if(class_exists('mysqli'))
- return mysqli_connect_errno();
- else
- return mysql_errno();
-}
-
-/**
- * @brief Get output for the setup page.
- *
- * Depending on the state we are currently in it returns different content.
- *
- * @param App &$a
- * @return string parsed HTML output
- */
-function setup_content(&$a) {
- global $install_wizard_pass, $db;
-
- $o = '';
- $wizard_status = '';
- $install_title = t('$Projectname Server - Setup');
-
- if(x(App::$data, 'db_conn_failed')) {
- $install_wizard_pass = 2;
- $wizard_status = t('Could not connect to database.');
- }
- if(x(App::$data, 'url_fail')) {
- $install_wizard_pass = 3;
- $wizard_status = t('Could not connect to specified site URL. Possible SSL certificate or DNS issue.');
- if(App::$data['url_error'])
- $wizard_status .= ' ' . App::$data['url_error'];
- }
-
- if(x(App::$data, 'db_create_failed')) {
- $install_wizard_pass = 2;
- $wizard_status = t('Could not create table.');
- }
- $db_return_text = '';
- if(x(App::$data, 'db_installed')) {
- $txt = '<p style="font-size: 130%;">';
- $txt .= t('Your site database has been installed.') . EOL;
- $db_return_text .= $txt;
- }
- if(x(App::$data, 'db_failed')) {
- $txt = t('You may need to import the file "install/schema_xxx.sql" manually using a database client.') . EOL;
- $txt .= t('Please see the file "install/INSTALL.txt".') . EOL ."<hr>" ;
- $txt .= "<pre>".App::$data['db_failed'] . "</pre>". EOL ;
- $db_return_text .= $txt;
- }
- if($db && $db->connected) {
- $r = q("SELECT COUNT(*) as `total` FROM `account`");
- if($r && count($r) && $r[0]['total']) {
- $tpl = get_markup_template('install.tpl');
- return replace_macros($tpl, array(
- '$title' => $install_title,
- '$pass' => '',
- '$status' => t('Permission denied.'),
- '$text' => '',
- ));
- }
- }
-
- if(x(App::$data, 'txt') && strlen(App::$data['txt'])) {
- $db_return_text .= manual_config($a);
- }
-
- if ($db_return_text != "") {
- $tpl = get_markup_template('install.tpl');
- return replace_macros($tpl, array(
- '$title' => $install_title,
- '$pass' => '',
- '$text' => $db_return_text . what_next(),
- ));
- }
-
- switch ($install_wizard_pass){
- case 1: { // System check
-
- $checks = array();
-
- check_funcs($checks);
-
- check_htconfig($checks);
-
- check_store($checks);
-
- check_smarty3($checks);
-
- check_keys($checks);
-
- if (x($_POST, 'phpath'))
- $phpath = notags(trim($_POST['phpath']));
-
- check_php($phpath, $checks);
-
- check_phpconfig($checks);
-
- check_htaccess($checks);
-
- function check_passed($v, $c) {
- if ($c['required'])
- $v = $v && $c['status'];
-
- return $v;
- }
- $checkspassed = array_reduce($checks, "check_passed", true);
-
- $tpl = get_markup_template('install_checks.tpl');
- $o .= replace_macros($tpl, array(
- '$title' => $install_title,
- '$pass' => t('System check'),
- '$checks' => $checks,
- '$passed' => $checkspassed,
- '$see_install' => t('Please see the file "install/INSTALL.txt".'),
- '$next' => t('Next'),
- '$reload' => t('Check again'),
- '$phpath' => $phpath,
- '$baseurl' => z_root(),
- ));
- return $o;
- }; break;
-
- case 2: { // Database config
-
- $dbhost = ((x($_POST,'dbhost')) ? notags(trim($_POST['dbhost'])) : '127.0.0.1');
- $dbuser = notags(trim($_POST['dbuser']));
- $dbport = intval(notags(trim($_POST['dbport'])));
- $dbpass = notags(trim($_POST['dbpass']));
- $dbdata = notags(trim($_POST['dbdata']));
- $dbtype = intval(notags(trim($_POST['dbtype'])));
- $phpath = notags(trim($_POST['phpath']));
- $adminmail = notags(trim($_POST['adminmail']));
- $siteurl = notags(trim($_POST['siteurl']));
-
- $tpl = get_markup_template('install_db.tpl');
- $o .= replace_macros($tpl, array(
- '$title' => $install_title,
- '$pass' => t('Database connection'),
- '$info_01' => t('In order to install $Projectname we need to know how to connect to your database.'),
- '$info_02' => t('Please contact your hosting provider or site administrator if you have questions about these settings.'),
- '$info_03' => t('The database you specify below should already exist. If it does not, please create it before continuing.'),
-
- '$status' => $wizard_status,
-
- '$dbhost' => array('dbhost', t('Database Server Name'), $dbhost, t('Default is 127.0.0.1')),
- '$dbport' => array('dbport', t('Database Port'), $dbport, t('Communication port number - use 0 for default')),
- '$dbuser' => array('dbuser', t('Database Login Name'), $dbuser, ''),
- '$dbpass' => array('dbpass', t('Database Login Password'), $dbpass, ''),
- '$dbdata' => array('dbdata', t('Database Name'), $dbdata, ''),
- '$dbtype' => array('dbtype', t('Database Type'), $dbtype, '', array( 0=>'MySQL', 1=>'PostgreSQL' )),
-
- '$adminmail' => array('adminmail', t('Site administrator email address'), $adminmail, t('Your account email address must match this in order to use the web admin panel.')),
- '$siteurl' => array('siteurl', t('Website URL'), z_root(), t('Please use SSL (https) URL if available.')),
- '$lbl_10' => t('Please select a default timezone for your website'),
-
- '$baseurl' => z_root(),
-
- '$phpath' => $phpath,
-
- '$submit' => t('Submit'),
- ));
- return $o;
- }; break;
- case 3: { // Site settings
- require_once('include/datetime.php');
- $dbhost = ((x($_POST,'dbhost')) ? notags(trim($_POST['dbhost'])) : '127.0.0.1');
- $dbport = intval(notags(trim($_POST['dbuser'])));
- $dbuser = notags(trim($_POST['dbuser']));
- $dbpass = notags(trim($_POST['dbpass']));
- $dbdata = notags(trim($_POST['dbdata']));
- $dbtype = intval(notags(trim($_POST['dbtype'])));
- $phpath = notags(trim($_POST['phpath']));
-
- $adminmail = notags(trim($_POST['adminmail']));
- $siteurl = notags(trim($_POST['siteurl']));
- $timezone = ((x($_POST,'timezone')) ? ($_POST['timezone']) : 'America/Los_Angeles');
-
- $tpl = get_markup_template('install_settings.tpl');
- $o .= replace_macros($tpl, array(
- '$title' => $install_title,
- '$pass' => t('Site settings'),
- '$status' => $wizard_status,
-
- '$dbhost' => $dbhost,
- '$dbport' => $dbport,
- '$dbuser' => $dbuser,
- '$dbpass' => $dbpass,
- '$dbdata' => $dbdata,
- '$phpath' => $phpath,
- '$dbtype' => $dbtype,
-
- '$adminmail' => array('adminmail', t('Site administrator email address'), $adminmail, t('Your account email address must match this in order to use the web admin panel.')),
-
- '$siteurl' => array('siteurl', t('Website URL'), z_root(), t('Please use SSL (https) URL if available.')),
- '$advanced' => array('advanced', t('Enable $Projectname <strong>advanced</strong> features?'), 1, t('Some advanced features, while useful - may be best suited for technically proficient audiences')),
-
- '$timezone' => array('timezone', t('Please select a default timezone for your website'), $timezone, '', get_timezones()),
-
- '$baseurl' => z_root(),
-
- '$submit' => t('Submit'),
- ));
- return $o;
- }; break;
- }
-}
-
-/**
- * @brief Add a check result to the array for output.
- *
- * @param[in,out] array &$checks array passed to template
- * @param string $title a title for the check
- * @param boolean $status
- * @param boolean $required
- * @param[optional] string $help optional help string
- */
-function check_add(&$checks, $title, $status, $required, $help = '') {
- $checks[] = array(
- 'title' => $title,
- 'status' => $status,
- 'required' => $required,
- 'help' => $help
- );
-}
-
-/**
- * @brief Checks the PHP environment.
- *
- * @param[in,out] string &$phpath
- * @param[out] array &$checks
- */
-function check_php(&$phpath, &$checks) {
- $help = '';
-
- if (strlen($phpath)) {
- $passed = file_exists($phpath);
- } else {
- if(is_windows())
- $phpath = trim(shell_exec('where php'));
- else
- $phpath = trim(shell_exec('which php'));
-
- $passed = strlen($phpath);
- }
-
- if(!$passed) {
- $help .= t('Could not find a command line version of PHP in the web server PATH.'). EOL;
- $help .= t('If you don\'t have a command line version of PHP installed on server, you will not be able to run background polling via cron.') . EOL;
- $help .= EOL . EOL ;
- $tpl = get_markup_template('field_input.tpl');
- $help .= replace_macros($tpl, array(
- '$field' => array('phpath', t('PHP executable path'), $phpath, t('Enter full path to php executable. You can leave this blank to continue the installation.')),
- ));
- $phpath = '';
- }
-
- check_add($checks, t('Command line PHP').($passed?" (<tt>$phpath</tt>)":""), $passed, false, $help);
-
- if($passed) {
- $str = autoname(8);
- $cmd = "$phpath install/testargs.php $str";
- $result = trim(shell_exec($cmd));
- $passed2 = $result == $str;
- $help = '';
- if(!$passed2) {
- $help .= t('The command line version of PHP on your system does not have "register_argc_argv" enabled.'). EOL;
- $help .= t('This is required for message delivery to work.');
- }
-
- check_add($checks, t('PHP register_argc_argv'), $passed, true, $help);
- }
-}
-
-/**
- * @brief Some PHP configuration checks.
- *
- * @todo Change how we display such informational text. Add more description
- * how to change them.
- *
- * @param[out] array &$checks
- */
-function check_phpconfig(&$checks) {
- require_once 'include/environment.php';
-
- $help = '';
-
- $result = getPhpiniUploadLimits();
- $help = sprintf(t('Your max allowed total upload size is set to %s. Maximum size of one file to upload is set to %s. You are allowed to upload up to %d files at once.'),
- userReadableSize($result['post_max_size']),
- userReadableSize($result['max_upload_filesize']),
- $result['max_file_uploads']
- );
- $help .= '<br>' . t('You can adjust these settings in the servers php.ini.');
-
- check_add($checks, t('PHP upload limits'), true, false, $help);
-}
-
-/**
- * @brief Check if the openssl implementation can generate keys.
- *
- * @param[out] array $checks
- */
-function check_keys(&$checks) {
- $help = '';
- $res = false;
-
- if (function_exists('openssl_pkey_new')) {
- $res = openssl_pkey_new(array(
- 'digest_alg' => 'sha1',
- 'private_key_bits' => 4096,
- 'encrypt_key' => false)
- );
- }
-
- // Get private key
-
- if (! $res) {
- $help .= t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys'). EOL;
- $help .= t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
- }
-
- check_add($checks, t('Generate encryption keys'), $res, true, $help);
-}
-
-/**
- * @brief Check for some PHP functions and modules.
- *
- * @param[in,out] array &$checks
- */
-function check_funcs(&$checks) {
- $ck_funcs = array();
-
- // add check metadata, the real check is done bit later and return values set
- check_add($ck_funcs, t('libCurl PHP module'), true, true);
- check_add($ck_funcs, t('GD graphics PHP module'), true, true);
- check_add($ck_funcs, t('OpenSSL PHP module'), true, true);
- check_add($ck_funcs, t('mysqli or postgres PHP module'), true, true);
- check_add($ck_funcs, t('mb_string PHP module'), true, true);
- check_add($ck_funcs, t('mcrypt PHP module'), true, true);
- check_add($ck_funcs, t('xml PHP module'), true, true);
-
- if(function_exists('apache_get_modules')){
- if (! in_array('mod_rewrite', apache_get_modules())) {
- check_add($ck_funcs, t('Apache mod_rewrite module'), false, true, t('Error: Apache webserver mod-rewrite module is required but not installed.'));
- } else {
- check_add($ck_funcs, t('Apache mod_rewrite module'), true, true);
- }
- }
- if((! function_exists('proc_open')) || strstr(ini_get('disable_functions'),'proc_open')) {
- check_add($ck_funcs, t('proc_open'), false, true, t('Error: proc_open is required but is either not installed or has been disabled in php.ini'));
- }
- else {
- check_add($ck_funcs, t('proc_open'), true, true);
- }
-
- if(! function_exists('curl_init')) {
- $ck_funcs[0]['status'] = false;
- $ck_funcs[0]['help'] = t('Error: libCURL PHP module required but not installed.');
- }
- if(! function_exists('imagecreatefromjpeg')) {
- $ck_funcs[1]['status'] = false;
- $ck_funcs[1]['help'] = t('Error: GD graphics PHP module with JPEG support required but not installed.');
- }
- if(! function_exists('openssl_public_encrypt')) {
- $ck_funcs[2]['status'] = false;
- $ck_funcs[2]['help'] = t('Error: openssl PHP module required but not installed.');
- }
- if(! function_exists('mysqli_connect') && !function_exists('pg_connect')) {
- $ck_funcs[3]['status'] = false;
- $ck_funcs[3]['help'] = t('Error: mysqli or postgres PHP module required but neither are installed.');
- }
- if(! function_exists('mb_strlen')) {
- $ck_funcs[4]['status'] = false;
- $ck_funcs[4]['help'] = t('Error: mb_string PHP module required but not installed.');
- }
- if(! function_exists('mcrypt_encrypt')) {
- $ck_funcs[5]['status'] = false;
- $ck_funcs[5]['help'] = t('Error: mcrypt PHP module required but not installed.');
- }
- if(! extension_loaded('xml')) {
- $ck_funcs[6]['status'] = false;
- $ck_funcs[6]['help'] = t('Error: xml PHP module required for DAV but not installed.');
- }
-
- $checks = array_merge($checks, $ck_funcs);
-}
-
-/**
- * @brief Check for .htconfig requirements.
- *
- * @param[out] array &$checks
- */
-function check_htconfig(&$checks) {
- $status = true;
- $help = '';
-
- if( (file_exists('.htconfig.php') && !is_writable('.htconfig.php')) ||
- (!file_exists('.htconfig.php') && !is_writable('.')) ) {
- $status = false;
- $help = t('The web installer needs to be able to create a file called ".htconfig.php" in the top folder of your web server and it is unable to do so.') .EOL;
- $help .= t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.').EOL;
- $help .= t('At the end of this procedure, we will give you a text to save in a file named .htconfig.php in your Red top folder.').EOL;
- $help .= t('You can alternatively skip this procedure and perform a manual installation. Please see the file "install/INSTALL.txt" for instructions.').EOL;
- }
-
- check_add($checks, t('.htconfig.php is writable'), $status, false, $help);
-}
-
-/**
- * @brief Checks for our templating engine Smarty3 requirements.
- *
- * @param[out] array &$checks
- */
-function check_smarty3(&$checks) {
- $status = true;
- $help = '';
-
- if(! is_writable(TEMPLATE_BUILD_PATH) ) {
- $status = false;
- $help = t('Red uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') .EOL;
- $help .= sprintf( t('In order to store these compiled templates, the web server needs to have write access to the directory %s under the Red top level folder.'), TEMPLATE_BUILD_PATH) . EOL;
- $help .= t('Please ensure that the user that your web server runs as (e.g. www-data) has write access to this folder.').EOL;
- $help .= sprintf( t('Note: as a security measure, you should give the web server write access to %s only--not the template files (.tpl) that it contains.'), TEMPLATE_BUILD_PATH) . EOL;
- }
-
- check_add($checks, sprintf( t('%s is writable'), TEMPLATE_BUILD_PATH), $status, true, $help);
-}
-
-/**
- * @brief Check for store directory.
- *
- * @param[out] array &$checks
- */
-function check_store(&$checks) {
- $status = true;
- $help = '';
-
- @os_mkdir(TEMPLATE_BUILD_PATH, STORAGE_DEFAULT_PERMISSIONS, true);
-
- if(! is_writable('store')) {
- $status = false;
- $help = t('Red uses the store directory to save uploaded files. The web server needs to have write access to the store directory under the Red top level folder') . EOL;
- $help .= t('Please ensure that the user that your web server runs as (e.g. www-data) has write access to this folder.').EOL;
- }
-
- check_add($checks, t('store is writable'), $status, true, $help);
-}
-
-/**
- * @brief Check URL rewrite und SSL certificate.
- *
- * @param[out] array &$checks
- */
-function check_htaccess(&$checks) {
- $a = get_app();
- $status = true;
- $help = '';
- $ssl_error = false;
-
- $url = z_root() . '/setup/testrewrite';
-
- if (function_exists('curl_init')){
- $test = z_fetch_url($url);
- if(! $test['success']) {
- if(strstr($url,'https://')) {
- $test = z_fetch_url($url,false,0,array('novalidate' => true));
- if($test['success']) {
- $ssl_error = true;
- }
- }
- else {
- $test = z_fetch_url(str_replace('http://','https://',$url),false,0,array('novalidate' => true));
- if($test['success']) {
- $ssl_error = true;
- }
- }
-
- if($ssl_error) {
- $help = t('SSL certificate cannot be validated. Fix certificate or disable https access to this site.') . EOL;
- $help .= t('If you have https access to your website or allow connections to TCP port 443 (the https: port), you MUST use a browser-valid certificate. You MUST NOT use self-signed certificates!') . EOL;
- $help .= t('This restriction is incorporated because public posts from you may for example contain references to images on your own hub.') . EOL;
- $help .= t('If your certificate is not recognized, members of other sites (who may themselves have valid certificates) will get a warning message on their own site complaining about security issues.') . EOL;
- $help .= t('This can cause usability issues elsewhere (not just on your own site) so we must insist on this requirement.') .EOL;
- $help .= t('Providers are available that issue free certificates which are browser-valid.'). EOL;
-
- check_add($checks, t('SSL certificate validation'), false, true, $help);
- }
- }
-
- if ((! $test['success']) || ($test['body'] != "ok")) {
- $status = false;
- $help = t('Url rewrite in .htaccess is not working. Check your server configuration.'.'Test: '.var_export($test,true));
- }
-
- check_add($checks, t('Url rewrite is working'), $status, true, $help);
- } else {
- // cannot check modrewrite if libcurl is not installed
- }
-}
-
-
-function manual_config(&$a) {
- $data = htmlspecialchars(App::$data['txt'], ENT_COMPAT, 'UTF-8');
- $o = t('The database configuration file ".htconfig.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.');
- $o .= "<textarea rows=\"24\" cols=\"80\" >$data</textarea>";
-
- return $o;
-}
-
-function load_database_rem($v, $i){
- $l = trim($i);
- if (strlen($l)>1 && ($l[0]=="-" || ($l[0]=="/" && $l[1]=="*"))){
- return $v;
- } else {
- return $v."\n".$i;
- }
-}
-
-
-function load_database($db) {
- $str = file_get_contents($db->get_install_script());
- $arr = explode(';',$str);
- $errors = false;
- foreach($arr as $a) {
- if(strlen(trim($a))) {
- $r = @$db->q(trim($a));
- if(! $r) {
- $errors .= t('Errors encountered creating database tables.') . $a . EOL;
- }
- }
- }
-
- return $errors;
-}
-
-function what_next() {
- $a = get_app();
- // install the standard theme
- set_config('system', 'allowed_themes', 'redbasic');
-
- // Set a lenient list of ciphers if using openssl. Other ssl engines
- // (e.g. NSS used in RedHat) require different syntax, so hopefully
- // the default curl cipher list will work for most sites. If not,
- // this can set via config. Many distros are now disabling RC4,
- // but many Red sites still use it and are unable to change it.
- // We do not use SSL for encryption, only to protect session cookies.
- // z_fetch_url() is also used to import shared links and other content
- // so in theory most any cipher could show up and we should do our best
- // to make the content available rather than tell folks that there's a
- // weird SSL error which they can't do anything about.
-
- $x = curl_version();
- if(stristr($x['ssl_version'],'openssl'))
- set_config('system','curl_ssl_ciphers','ALL:!eNULL');
-
- // Create a system channel
- require_once ('include/identity.php');
- create_sys_channel();
-
- $baseurl = z_root();
- return
- t('<h1>What next</h1>')
- ."<p>".t('IMPORTANT: You will need to [manually] setup a scheduled task for the poller.')
- .t('Please see the file "install/INSTALL.txt".')
- ."</p><p>"
- .t("Go to your new hub <a href='$baseurl/register'>registration page</a> and register as new member. Remember to use the same email you have entered as administrator email. This will allow you to enter the site admin panel.")
- ."</p>";
-}
diff --git a/mod/share.php b/mod/share.php
deleted file mode 100644
index 43206b487..000000000
--- a/mod/share.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-
-require_once('include/security.php');
-require_once('include/bbcode.php');
-
-function share_init(&$a) {
-
- $post_id = ((argc() > 1) ? intval(argv(1)) : 0);
-
- if(! $post_id)
- killme();
-
- if(! (local_channel() || remote_channel()))
- killme();
-
- $r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1",
- intval($post_id)
- );
- if(! $r)
- killme();
- if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss'))
- killme();
-
- $sql_extra = item_permissions_sql($r[0]['uid']);
-
- $r = q("select * from item where id = %d $sql_extra",
- intval($post_id)
- );
- if(! $r)
- killme();
-
- /** @FIXME we only share bbcode */
-
- if($r[0]['mimetype'] !== 'text/bbcode')
- killme();
-
- /** @FIXME eventually we want to post remotely via rpost on your home site */
- // When that works remove this next bit:
-
- if(! local_channel())
- killme();
-
- xchan_query($r);
-
- $is_photo = (($r[0]['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
- if($is_photo) {
- $object = json_decode($r[0]['object'],true);
- $photo_bb = $object['body'];
- }
-
- if (strpos($r[0]['body'], "[/share]") !== false) {
- $pos = strpos($r[0]['body'], "[share");
- $o = substr($r[0]['body'], $pos);
- } else {
- $o = "[share author='".urlencode($r[0]['author']['xchan_name']).
- "' profile='".$r[0]['author']['xchan_url'] .
- "' avatar='".$r[0]['author']['xchan_photo_s'].
- "' link='".$r[0]['plink'].
- "' posted='".$r[0]['created'].
- "' message_id='".$r[0]['mid']."']";
- if($r[0]['title'])
- $o .= '[b]'.$r[0]['title'].'[/b]'."\r\n";
- $o .= (($is_photo) ? $photo_bb . "\r\n" . $r[0]['body'] : $r[0]['body']);
- $o .= "[/share]";
- }
-
- if(local_channel()) {
- echo $o;
- killme();
- }
-
- $observer = App::get_observer();
- $parsed = $observer['xchan_url'];
- if($parsed) {
- $post_url = $parsed['scheme'] . ':' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '')
- . '/rpost';
-
- /**
- * @FIXME we were probably called from JS so we don't know the return page.
- * In fact we won't be able to load the remote page.
- * we might need an iframe
- */
-
- $x = z_post_url($post_url, array('f' => '', 'body' => $o ));
- killme();
- }
-}
diff --git a/mod/sharedwithme.php b/mod/sharedwithme.php
deleted file mode 100644
index 27c238270..000000000
--- a/mod/sharedwithme.php
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-require_once('include/conversation.php');
-require_once('include/text.php');
-
-function sharedwithme_content(&$a) {
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- $channel = App::get_channel();
-
- $is_owner = (local_channel() && (local_channel() == $channel['channel_id']));
-
- //check for updated items and remove them
- require_once('include/sharedwithme.php');
- apply_updates();
-
- //drop single file - localuser
- if((argc() > 2) && (argv(2) === 'drop')) {
-
- $id = intval(argv(1));
-
- q("DELETE FROM item WHERE id = %d AND uid = %d",
- intval($id),
- intval(local_channel())
- );
-
- goaway(z_root() . '/sharedwithme');
- }
-
- //drop all files - localuser
- if((argc() > 1) && (argv(1) === 'dropall')) {
-
- q("DELETE FROM item WHERE verb = '%s' AND obj_type = '%s' AND uid = %d",
- dbesc(ACTIVITY_POST),
- dbesc(ACTIVITY_OBJ_FILE),
- intval(local_channel())
- );
-
- goaway(z_root() . '/sharedwithme');
- }
-
- //list files
- $r = q("SELECT id, uid, object, item_unseen FROM item WHERE verb = '%s' AND obj_type = '%s' AND uid = %d AND owner_xchan != '%s'",
- dbesc(ACTIVITY_POST),
- dbesc(ACTIVITY_OBJ_FILE),
- intval(local_channel()),
- dbesc($channel['channel_hash'])
- );
-
- $items =array();
- $ids = '';
-
- if($r) {
-
- foreach($r as $rr) {
- $object = json_decode($rr['object'],true);
-
- $item = array();
- $item['id'] = $rr['id'];
- $item['objfiletype'] = $object['filetype'];
- $item['objfiletypeclass'] = getIconFromType($object['filetype']);
- $item['objurl'] = rawurldecode(get_rel_link($object['link'],'alternate')) . '?f=&zid=' . $channel['xchan_addr'];
- $item['objfilename'] = $object['filename'];
- $item['objfilesize'] = userReadableSize($object['filesize']);
- $item['objedited'] = $object['edited'];
- $item['unseen'] = $rr['item_unseen'];
-
- $items[] = $item;
-
- if($item['unseen'] > 0) {
- $ids .= " '" . $rr['id'] . "',";
- }
-
- }
-
- }
-
- if($ids) {
-
- //remove trailing ,
- $ids = rtrim($ids, ",");
-
- q("UPDATE item SET item_unseen = 0 WHERE id IN ( $ids ) AND uid = %d",
- intval(local_channel())
- );
-
- }
-
- $o = profile_tabs($a, $is_owner, $channel['channel_address']);
-
- $o .= replace_macros(get_markup_template('sharedwithme.tpl'), array(
- '$header' => t('Files: shared with me'),
- '$name' => t('Name'),
- '$label_new' => t('NEW'),
- '$size' => t('Size'),
- '$lastmod' => t('Last Modified'),
- '$dropall' => t('Remove all files'),
- '$drop' => t('Remove this file'),
- '$items' => $items
- ));
-
- return $o;
-
-}
-
diff --git a/mod/siteinfo.php b/mod/siteinfo.php
deleted file mode 100644
index 7711fafb2..000000000
--- a/mod/siteinfo.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-
-function siteinfo_init(&$a) {
- if (argv(1) === 'json') {
- $data = get_site_info();
- json_return_and_die($data);
- }
-}
-
-
-
-function siteinfo_content(&$a) {
-
- if(! get_config('system','hidden_version_siteinfo')) {
- $version = sprintf( t('Version %s'), Zotlabs\Project\System::get_project_version());
- if(@is_dir('.git') && function_exists('shell_exec')) {
- $commit = @shell_exec('git log -1 --format="%h"');
- $tag = Zotlabs\Project\System::get_std_version(); // @shell_exec('git describe --tags --abbrev=0');
- }
- if(! isset($commit) || strlen($commit) > 16)
- $commit = '';
- }
- else {
- $version = $commit = '';
- }
- $visible_plugins = array();
- if(is_array(App::$plugins) && count(App::$plugins)) {
- $r = q("select * from addon where hidden = 0");
- if(count($r))
- foreach($r as $rr)
- $visible_plugins[] = $rr['name'];
- }
-
- $plugins_list = '';
- if(count($visible_plugins)) {
- $plugins_text = t('Installed plugins/addons/apps:');
- $sorted = $visible_plugins;
- $s = '';
- sort($sorted);
- foreach($sorted as $p) {
- if(strlen($p)) {
- if(strlen($s)) $s .= ', ';
- $s .= $p;
- }
- }
- $plugins_list .= $s;
- }
- else
- $plugins_text = t('No installed plugins/addons/apps');
-
- $txt = get_config('system','admininfo');
- $admininfo = bbcode($txt);
-
- if(file_exists('doc/site_donate.html'))
- $donate .= file_get_contents('doc/site_donate.html');
-
- if(function_exists('sys_getloadavg'))
- $loadavg = sys_getloadavg();
-
- $o = replace_macros(get_markup_template('siteinfo.tpl'), array(
- '$title' => t('$Projectname'),
- '$description' => t('This is a hub of $Projectname - a global cooperative network of decentralized privacy enhanced websites.'),
- '$version' => $version,
- '$tag_txt' => t('Tag: '),
- '$tag' => $tag,
- '$polled' => t('Last background fetch: '),
- '$lastpoll' => get_poller_runtime(),
- '$load_average' => t('Current load average: '),
- '$loadavg_all' => $loadavg[0] . ', ' . $loadavg[1] . ', ' . $loadavg[2],
- '$commit' => $commit,
- '$web_location' => t('Running at web location') . ' ' . z_root(),
- '$visit' => t('Please visit <a href="http://hubzilla.org">hubzilla.org</a> to learn more about $Projectname.'),
- '$bug_text' => t('Bug reports and issues: please visit'),
- '$bug_link_url' => 'https://github.com/redmatrix/hubzilla/issues',
- '$bug_link_text' => t('$projectname issues'),
- '$contact' => t('Suggestions, praise, etc. - please email "redmatrix" at librelist - dot com'),
- '$donate' => $donate,
- '$adminlabel' => t('Site Administrators'),
- '$admininfo' => $admininfo,
- '$plugins_text' => $plugins_text,
- '$plugins_list' => $plugins_list
- ));
-
- call_hooks('about_hook', $o);
-
- return $o;
-
-}
diff --git a/mod/siteinfo_json.php b/mod/siteinfo_json.php
deleted file mode 100644
index 35697917c..000000000
--- a/mod/siteinfo_json.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-function siteinfo_json_init(&$a) {
-
- $data = get_site_info();
- json_return_and_die($data);
-
-}
diff --git a/mod/sitelist.php b/mod/sitelist.php
deleted file mode 100644
index 30b2359ac..000000000
--- a/mod/sitelist.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php /** @file */
-
-function sitelist_init(&$a) {
-
- $start = (($_REQUEST['start']) ? intval($_REQUEST['start']) : 0);
- $limit = ((intval($_REQUEST['limit'])) ? intval($_REQUEST['limit']) : 30);
- $order = (($_REQUEST['order']) ? $_REQUEST['order'] : 'random');
- $open = (($_REQUEST['open']) ? intval($_REQUEST['open']) : false);
-
-
- $sql_order = " order by site_url ";
- $rand = db_getfunc('rand');
- if($order == 'random')
- $sql_order = " order by $rand ";
-
- $sql_limit = " LIMIT $limit OFFSET $start ";
-
- $sql_extra = "";
- if($open)
- $sql_extra = " and site_register = " . intval(REGISTER_OPEN) . " ";
-
- $realm = get_directory_realm();
- if($realm == DIRECTORY_REALM) {
- $sql_extra .= " and ( site_realm = '" . dbesc($realm) . "' or site_realm = '') ";
- }
- else
- $sql_extra .= " and site_realm = '" . dbesc($realm) . "' ";
-
- $result = array('success' => false);
-
- $r = q("select count(site_url) as total from site where site_type = %d $sql_extra ",
- intval(SITE_TYPE_ZOT)
- );
-
- if($r)
- $result['total'] = intval($r[0]['total']);
-
- $result['start'] = $start;
- $result['limit'] = $limit;
-
- $r = q("select * from site where site_type = %d $sql_extra $sql_order $sql_limit",
- intval(SITE_TYPE_ZOT)
- );
-
- $result['results'] = 0;
- $result['entries'] = array();
-
- if($r) {
- $result['success'] = true;
- $result['results'] = count($r);
-
- foreach($r as $rr) {
- $result['entries'][] = array('url' => $rr['site_url']);
- }
-
- }
-
- echo json_encode($result);
- killme();
-
-
-} \ No newline at end of file
diff --git a/mod/smilies.php b/mod/smilies.php
deleted file mode 100644
index 2ccc007b4..000000000
--- a/mod/smilies.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-function smilies_content(&$a) {
- if (App::$argv[1]==="json"){
- $tmp = list_smilies();
- $results = array();
- for($i = 0; $i < count($tmp['texts']); $i++) {
- $results[] = array('text' => $tmp['texts'][$i], 'icon' => $tmp['icons'][$i]);
- }
- json_return_and_die($results);
- }
- else {
- return smilies('',true);
- }
-}
diff --git a/mod/sources.php b/mod/sources.php
deleted file mode 100644
index 6ea0743aa..000000000
--- a/mod/sources.php
+++ /dev/null
@@ -1,168 +0,0 @@
-<?php /** @file */
-
-function sources_post(&$a) {
- if(! local_channel())
- return;
-
- if(! feature_enabled(local_channel(),'channel_sources'))
- return '';
-
- $source = intval($_REQUEST['source']);
- $xchan = $_REQUEST['xchan'];
- $abook = intval($_REQUEST['abook']);
- $words = $_REQUEST['words'];
- $frequency = $_REQUEST['frequency'];
- $name = $_REQUEST['name'];
-
- $channel = App::get_channel();
-
- if($name == '*')
- $xchan = '*';
-
- if($abook) {
- $r = q("select abook_xchan from abook where abook_id = %d and abook_channel = %d limit 1",
- intval($abook),
- intval(local_channel())
- );
- if($r)
- $xchan = $r[0]['abook_xchan'];
- }
-
- if(! $xchan) {
- notice ( t('Failed to create source. No channel selected.') . EOL);
- return;
- }
-
- if(! $source) {
- $r = q("insert into source ( src_channel_id, src_channel_xchan, src_xchan, src_patt )
- values ( %d, '%s', '%s', '%s' ) ",
- intval(local_channel()),
- dbesc($channel['channel_hash']),
- dbesc($xchan),
- dbesc($words)
- );
- if($r) {
- info( t('Source created.') . EOL);
- }
- goaway(z_root() . '/sources');
- }
- else {
- $r = q("update source set src_xchan = '%s', src_patt = '%s' where src_channel_id = %d and src_id = %d",
- dbesc($xchan),
- dbesc($words),
- intval(local_channel()),
- intval($source)
- );
- if($r) {
- info( t('Source updated.') . EOL);
- }
-
- }
-}
-
-
-function sources_content(&$a) {
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return '';
- }
-
- if(! feature_enabled(local_channel(),'channel_sources')) {
- return '';
- }
-
- // list sources
- if(argc() == 1) {
- $r = q("select source.*, xchan.* from source left join xchan on src_xchan = xchan_hash where src_channel_id = %d",
- intval(local_channel())
- );
- if($r) {
- for($x = 0; $x < count($r); $x ++) {
- if($r[$x]['src_xchan'] == '*') {
- $r[$x]['xchan_name'] = t('*');
- }
- $r[$x]['src_patt'] = htmlspecialchars($r[$x]['src_patt'], ENT_COMPAT,'UTF-8');
- }
- }
- $o = replace_macros(get_markup_template('sources_list.tpl'), array(
- '$title' => t('Channel Sources'),
- '$desc' => t('Manage remote sources of content for your channel.'),
- '$new' => t('New Source'),
- '$sources' => $r
- ));
- return $o;
- }
-
- if(argc() == 2 && argv(1) === 'new') {
- // TODO add the words 'or RSS feed' and corresponding code to manage feeds and frequency
-
- $o = replace_macros(get_markup_template('sources_new.tpl'), array(
- '$title' => t('New Source'),
- '$desc' => t('Import all or selected content from the following channel into this channel and distribute it according to your channel settings.'),
- '$words' => array( 'words', t('Only import content with these words (one per line)'),'',t('Leave blank to import all public content')),
- '$name' => array( 'name', t('Channel Name'), '', ''),
- '$submit' => t('Submit')
- ));
- return $o;
-
- }
-
- if(argc() == 2 && intval(argv(1))) {
- // edit source
- $r = q("select source.*, xchan.* from source left join xchan on src_xchan = xchan_hash where src_id = %d and src_channel_id = %d limit 1",
- intval(argv(1)),
- intval(local_channel())
- );
- if($r) {
- $x = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
- dbesc($r[0]['src_xchan']),
- intval(local_channel())
- );
- }
- if(! $r) {
- notice( t('Source not found.') . EOL);
- return '';
- }
-
- $r[0]['src_patt'] = htmlspecialchars($r[0]['src_patt'], ENT_QUOTES,'UTF-8');
-
- $o = replace_macros(get_markup_template('sources_edit.tpl'), array(
- '$title' => t('Edit Source'),
- '$drop' => t('Delete Source'),
- '$id' => $r[0]['src_id'],
- '$desc' => t('Import all or selected content from the following channel into this channel and distribute it according to your channel settings.'),
- '$words' => array( 'words', t('Only import content with these words (one per line)'),$r[0]['src_patt'],t('Leave blank to import all public content')),
- '$xchan' => $r[0]['src_xchan'],
- '$abook' => $x[0]['abook_id'],
- '$name' => array( 'name', t('Channel Name'), $r[0]['xchan_name'], ''),
- '$submit' => t('Submit')
- ));
- return $o;
-
- }
-
- if(argc() == 3 && intval(argv(1)) && argv(2) === 'drop') {
- $r = q("select * from source where src_id = %d and src_channel_id = %d limit 1",
- intval(argv(1)),
- intval(local_channel())
- );
- if(! $r) {
- notice( t('Source not found.') . EOL);
- return '';
- }
- $r = q("delete from source where src_id = %d and src_channel_id = %d",
- intval(argv(1)),
- intval(local_channel())
- );
- if($r)
- info( t('Source removed') . EOL);
- else
- notice( t('Unable to remove source.') . EOL);
-
- goaway(z_root() . '/sources');
-
- }
-
- // shouldn't get here.
-
-} \ No newline at end of file
diff --git a/mod/sslify.php b/mod/sslify.php
deleted file mode 100644
index f37a8e23e..000000000
--- a/mod/sslify.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-function sslify_init(&$a) {
- $x = z_fetch_url($_REQUEST['url']);
- if($x['success']) {
- $h = explode("\n",$x['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'];
-
- header('Content-Type: ' . $type);
- echo $x['body'];
- killme();
- }
- killme();
- // for some reason when this fallback is in place - it gets triggered
- // often, (creating mixed content exceptions) even though there is
- // nothing obvious missing on the page when we bypass it.
- goaway($_REQUEST['url']);
-}
-
diff --git a/mod/starred.php b/mod/starred.php
deleted file mode 100644
index 103e5f4b4..000000000
--- a/mod/starred.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-
-function starred_init(&$a) {
-
- $starred = 0;
-
- if(! local_channel())
- killme();
- if(argc() > 1)
- $message_id = intval(argv(1));
- if(! $message_id)
- killme();
-
- $r = q("SELECT item_flags FROM item WHERE uid = %d AND id = %d LIMIT 1",
- intval(local_channel()),
- intval($message_id)
- );
- if(! count($r))
- killme();
-
- $item_starred = (intval($r[0]['item_starred']) ? 0 : 1);
-
- $r = q("UPDATE item SET item_starred = %d WHERE uid = %d and id = %d",
- intval($item_starred),
- intval(local_channel()),
- intval($message_id)
- );
-
- header('Content-type: application/json');
- echo json_encode(array('result' => $item_starred));
- killme();
-}
diff --git a/mod/subthread.php b/mod/subthread.php
deleted file mode 100755
index aca034d43..000000000
--- a/mod/subthread.php
+++ /dev/null
@@ -1,163 +0,0 @@
-<?php
-
-require_once('include/security.php');
-require_once('include/bbcode.php');
-require_once('include/items.php');
-
-
-function subthread_content(&$a) {
-
- if((! local_channel()) && (! remote_channel())) {
- return;
- }
-
- $item_id = ((argc() > 2) ? notags(trim(argv(2))) : 0);
-
- if(argv(1) === 'sub')
- $activity = ACTIVITY_FOLLOW;
- elseif(argv(1) === 'unsub')
- $activity = ACTIVITY_UNFOLLOW;
-
-
- $r = q("SELECT parent FROM item WHERE id = '%s'",
- dbesc($item_id)
- );
-
- if($r) {
- $r = q("select * from item where id = parent and id = %d limit 1",
- dbesc($r[0]['parent'])
- );
- }
-
- if((! $item_id) || (! $r)) {
- logger('subthread: no item ' . $item_id);
- return;
- }
-
- $item = $r[0];
-
- $owner_uid = $item['uid'];
- $observer = App::get_observer();
- $ob_hash = (($observer) ? $observer['xchan_hash'] : '');
-
- if(! perm_is_allowed($owner_uid,$ob_hash,'post_comments'))
- return;
-
- $sys = get_sys_channel();
-
- $owner_uid = $item['uid'];
- $owner_aid = $item['aid'];
-
- // if this is a "discover" item, (item['uid'] is the sys channel),
- // fallback to the item comment policy, which should've been
- // respected when generating the conversation thread.
- // Even if the activity is rejected by the item owner, it should still get attached
- // to the local discover conversation on this site.
-
- 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();
-
-
-
-
- $mid = item_message_id();
-
- $post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
-
- $links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
- $objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
-
- $body = $item['body'];
-
- $obj = json_encode(array(
- 'type' => $objtype,
- 'id' => $item['mid'],
- 'parent' => (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']),
- 'link' => $links,
- 'title' => $item['title'],
- 'content' => $item['body'],
- 'created' => $item['created'],
- 'edited' => $item['edited'],
- 'author' => array(
- 'name' => $item_author['xchan_name'],
- 'address' => $item_author['xchan_addr'],
- 'guid' => $item_author['xchan_guid'],
- 'guid_sig' => $item_author['xchan_guid_sig'],
- 'link' => array(
- array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']),
- array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])),
- ),
- ));
-
- if(! intval($item['item_thread_top']))
- $post_type = 'comment';
-
- if($activity === ACTIVITY_FOLLOW)
- $bodyverb = t('%1$s is following %2$s\'s %3$s');
- if($activity === ACTIVITY_UNFOLLOW)
- $bodyverb = t('%1$s stopped following %2$s\'s %3$s');
-
- $arr = array();
-
- $arr['mid'] = $mid;
- $arr['aid'] = $owner_aid;
- $arr['uid'] = $owner_uid;
- $arr['parent'] = $item['id'];
- $arr['parent_mid'] = $item['mid'];
- $arr['thr_parent'] = $item['mid'];
- $arr['owner_xchan'] = $thread_owner['xchan_hash'];
- $arr['author_xchan'] = $observer['xchan_hash'];
- $arr['item_origin'] = 1;
- $arr['item_notshown'] = 1;
- if(intval($item['item_wall']))
- $arr['item_wall'] = 1;
- else
- $arr['item_wall'] = 0;
-
- $ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]';
- $alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
- $plink = '[zrl=' . z_root() . '/display/' . $item['mid'] . ']' . $post_type . '[/zrl]';
-
- $arr['body'] = sprintf( $bodyverb, $alink, $ulink, $plink );
-
- $arr['verb'] = $activity;
- $arr['obj_type'] = $objtype;
- $arr['object'] = $obj;
-
- $arr['allow_cid'] = $item['allow_cid'];
- $arr['allow_gid'] = $item['allow_gid'];
- $arr['deny_cid'] = $item['deny_cid'];
- $arr['deny_gid'] = $item['deny_gid'];
-
- $post = item_store($arr);
- $post_id = $post['item_id'];
-
- $arr['id'] = $post_id;
-
- call_hooks('post_local_end', $arr);
-
- killme();
-
-
-}
-
-
-
diff --git a/mod/suggest.php b/mod/suggest.php
deleted file mode 100644
index ca888310a..000000000
--- a/mod/suggest.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-require_once('include/socgraph.php');
-require_once('include/contact_widgets.php');
-require_once('include/widgets.php');
-
-
-function suggest_init(&$a) {
- if(! local_channel())
- return;
-
- if(x($_GET,'ignore')) {
- q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
- intval(local_channel()),
- dbesc($_GET['ignore'])
- );
- }
-
-}
-
-
-function suggest_content(&$a) {
-
- $o = '';
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- $_SESSION['return_url'] = z_root() . '/' . App::$cmd;
-
- $r = suggestion_query(local_channel(),get_observer_hash());
-
- if(! $r) {
- info( t('No suggestions available. If this is a new site, please try again in 24 hours.'));
- return;
- }
-
- $arr = array();
-
- foreach($r as $rr) {
-
- $connlnk = z_root() . '/follow/?url=' . $rr['xchan_addr'];
-
- $arr[] = array(
- 'url' => chanlink_url($rr['xchan_url']),
- 'common' => $rr['total'],
- 'profile' => $rr['xchan_url'],
- 'name' => $rr['xchan_name'],
- 'photo' => $rr['xchan_photo_m'],
- 'ignlnk' => z_root() . '/suggest?ignore=' . $rr['xchan_hash'],
- 'conntxt' => t('Connect'),
- 'connlnk' => $connlnk,
- 'ignore' => t('Ignore/Hide')
- );
- }
-
-
- $o = replace_macros(get_markup_template('suggest_page.tpl'),array(
- '$title' => t('Channel Suggestions'),
- '$entries' => $arr
- ));
-
- return $o;
-
-}
diff --git a/mod/tagger.php b/mod/tagger.php
deleted file mode 100644
index 330b65b91..000000000
--- a/mod/tagger.php
+++ /dev/null
@@ -1,134 +0,0 @@
-<?php
-
-require_once('include/security.php');
-require_once('include/bbcode.php');
-require_once('include/items.php');
-
-
-function tagger_content(&$a) {
-
- if(! local_channel() && ! remote_channel()) {
- return;
- }
-
- $observer_hash = get_observer_hash();
- //strip html-tags
- $term = notags(trim($_GET['term']));
- //check if empty
- if(! $term)
- return;
-
- $item_id = ((argc() > 1) ? notags(trim(argv(1))) : 0);
-
- logger('tagger: tag ' . $term . ' item ' . $item_id);
-
-
- $r = q("SELECT * FROM item left join xchan on xchan_hash = author_xchan WHERE id = '%s' and uid = %d LIMIT 1",
- dbesc($item_id),
- intval(local_channel())
- );
-
- if((! $item_id) || (! $r)) {
- logger('tagger: no item ' . $item_id);
- return;
- }
-
- $item = $r[0];
-
- $owner_uid = $item['uid'];
-
- switch($item['resource_type']) {
- case 'photo':
- $targettype = ACTIVITY_OBJ_PHOTO;
- $post_type = t('photo');
- break;
- case 'event':
- $targgettype = ACTIVITY_OBJ_EVENT;
- $post_type = t('event');
- break;
- default:
- $targettype = ACTIVITY_OBJ_NOTE;
- $post_type = t('post');
- if($item['mid'] != $item['parent_mid'])
- $post_type = t('comment');
- break;
- }
-
-
- $links = array(array('rel' => 'alternate','type' => 'text/html',
- 'href' => z_root() . '/display/' . $item['mid']));
-
- $target = json_encode(array(
- 'type' => $targettype,
- 'id' => $item['mid'],
- 'link' => $links,
- 'title' => $item['title'],
- 'content' => $item['body'],
- 'created' => $item['created'],
- 'edited' => $item['edited'],
- 'author' => array(
- 'name' => $item['xchan_name'],
- 'address' => $item['xchan_addr'],
- 'guid' => $item['xchan_guid'],
- 'guid_sig' => $item['xchan_guid_sig'],
- 'link' => array(
- array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item['xchan_url']),
- array('rel' => 'photo', 'type' => $item['xchan_photo_mimetype'], 'href' => $item['xchan_photo_m'])),
- ),
- ));
-
-
-
- $link = xmlify('<link rel="alternate" type="text/html" href="'
- . z_root() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n") ;
-
- $tagid = z_root() . '/search?tag=' . $term;
- $objtype = ACTIVITY_OBJ_TAGTERM;
-
- $obj = json_encode(array(
- 'type' => $objtype,
- 'id' => $tagid,
- 'link' => array(array('rel' => 'alternate','type' => 'text/html', 'href' => $tagid)),
- 'title' => $term,
- 'content' => $term
- ));
-
- $bodyverb = t('%1$s tagged %2$s\'s %3$s with %4$s');
-
- // saving here for reference
- // also check out x22d5 and x2317 and x0d6b and x0db8 and x24d0 and xff20 !!!
-
- $termlink = html_entity_decode('&#x22d5;') . '[zrl=' . z_root() . '/search?tag=' . urlencode($term) . ']'. $term . '[/zrl]';
-
- $channel = App::get_channel();
-
- $arr = array();
-
- $arr['owner_xchan'] = $item['owner_xchan'];
- $arr['author_xchan'] = $channel['channel_hash'];
-
- $arr['item_origin'] = 1;
- $arr['item_wall'] = ((intval($item['item_wall'])) ? 1 : 0);
-
- $ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]';
- $alink = '[zrl=' . $item['xchan_url'] . ']' . $item['xchan_name'] . '[/zrl]';
- $plink = '[zrl=' . $item['plink'] . ']' . $post_type . '[/zrl]';
-
- $arr['body'] = sprintf( $bodyverb, $ulink, $alink, $plink, $termlink );
-
- $arr['verb'] = ACTIVITY_TAG;
- $arr['tgt_type'] = $targettype;
- $arr['target'] = $target;
- $arr['obj_type'] = $objtype;
- $arr['object'] = $obj;
- $arr['parent_mid'] = $item['mid'];
-
- store_item_tag($item['uid'],$item['id'],TERM_OBJ_POST,TERM_COMMUNITYTAG,$term,$tagid);
- $ret = post_activity_item($arr);
-
- if($ret['success'])
- proc_run('php','include/notifier.php','tag',$ret['activity']['id']);
-
- killme();
-
-}
diff --git a/mod/tagrm.php b/mod/tagrm.php
deleted file mode 100644
index e10bbad73..000000000
--- a/mod/tagrm.php
+++ /dev/null
@@ -1,141 +0,0 @@
-<?php
-
-require_once('include/bbcode.php');
-
-function tagrm_post(&$a) {
-
- if(! local_channel())
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
-
- if((x($_POST,'submit')) && ($_POST['submit'] === t('Cancel')))
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
- $tag = ((x($_POST,'tag')) ? trim($_POST['tag']) : '');
- $item = ((x($_POST,'item')) ? intval($_POST['item']) : 0 );
-
- $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval($item),
- intval(local_channel())
- );
-
- if(! $r)
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
- $r = fetch_post_tags($r,true);
-
- $item = $r[0];
- $new_tags = array();
-
- if($item['term']) {
- for($x = 0; $x < count($item['term']); $x ++) {
- if($item['term'][$x]['term'] !== hex2bin($tag))
- $new_tags[] = $item['term'][$x];
- }
- }
-
- if($new_tags)
- $item['term'] = $new_tags;
- else
- unset($item['term']);
-
- item_store_update($item);
-
- info( t('Tag removed') . EOL );
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
- // NOTREACHED
-
-}
-
-
-
-function tagrm_content(&$a) {
-
- if(! local_channel()) {
- goaway(z_root() . '/' . $_SESSION['photo_return']);
- // NOTREACHED
- }
-
- // remove tag on the fly if item and tag are provided
- if((argc() == 4) && (argv(1) === 'drop') && intval(argv(2))) {
-
- $item = intval(argv(2));
- $tag = argv(3);
-
- $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval($item),
- intval(local_channel())
- );
-
- if(! $r)
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
- $r = fetch_post_tags($r,true);
-
- $item = $r[0];
-
- $new_tags = array();
-
- if($item['term']) {
- for($x = 0; $x < count($item['term']); $x ++) {
- if($item['term'][$x]['term'] !== hex2bin($tag))
- $new_tags[] = $item['term'][$x];
- }
- }
-
- if($new_tags)
- $item['term'] = $new_tags;
- else
- unset($item['term']);
-
- item_store_update($item);
-
- info( t('Tag removed') . EOL );
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
- }
-
- //if we got only the item print a list of tags to select
- if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
-
- $o = '';
-
- $item = intval(argv(2));
-
- $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval($item),
- intval(local_channel())
- );
-
- if(! $r)
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
- $r = fetch_post_tags($r,true);
-
- if(! count($r[0]['term']))
- goaway(z_root() . '/' . $_SESSION['photo_return']);
-
- $o .= '<h3>' . t('Remove Item Tag') . '</h3>';
-
- $o .= '<p id="tag-remove-desc">' . t('Select a tag to remove: ') . '</p>';
-
- $o .= '<form id="tagrm" action="tagrm" method="post" >';
- $o .= '<input type="hidden" name="item" value="' . $item . '" />';
- $o .= '<ul>';
-
-
- foreach($r[0]['term'] as $x) {
- $o .= '<li><input type="checkbox" name="tag" value="' . bin2hex($x['term']) . '" >' . bbcode($x['term']) . '</input></li>';
- }
-
- $o .= '</ul>';
- $o .= '<input id="tagrm-submit" type="submit" name="submit" value="' . t('Remove') .'" />';
- $o .= '<input id="tagrm-cancel" type="submit" name="submit" value="' . t('Cancel') .'" />';
- $o .= '</form>';
-
- return $o;
-
- }
-
-}
diff --git a/mod/tasks.php b/mod/tasks.php
deleted file mode 100644
index e11166f93..000000000
--- a/mod/tasks.php
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-
-require_once('include/event.php');
-
-
-function tasks_init(&$a) {
-
-
-// logger('request: ' . print_r($_REQUEST,true));
-
- $arr = array();
-
- if(argc() > 1 && argv(1) === 'fetch') {
- if(argc() > 2 && argv(2) === 'all')
- $arr['all'] = 1;
-
- $x = tasks_fetch($arr);
- if($x['tasks']) {
- $x['html'] = '';
- foreach($x['tasks'] as $y) {
- $x['html'] .= '<div class="tasklist-item"><input type="checkbox" onchange="taskComplete(' . $y['id'] . '); return false;" /> ' . $y['summary'] . '</div>';
- }
- }
- json_return_and_die($x);
- }
-
-}
-
-
-
-function tasks_post(&$a) {
-
-
-// logger('post: ' . print_r($_POST,true));
-
-
- if(! local_channel())
- return;
-
- $channel = App::get_channel();
-
- if((argc() > 2) && (argv(1) === 'complete') && intval(argv(2))) {
- $ret = array('success' => false);
- $r = q("select * from event where `type` = 'task' and uid = %d and id = %d limit 1",
- intval(local_channel()),
- intval(argv(2))
- );
- if($r) {
- $event = $r[0];
- if($event['event_status'] === 'COMPLETED') {
- $event['event_status'] = 'IN-PROCESS';
- $event['event_status_date'] = NULL_DATE;
- $event['event_percent'] = 0;
- $event['event_sequence'] = $event['event_sequence'] + 1;
- $event['edited'] = datetime_convert();
- }
- else {
- $event['event_status'] = 'COMPLETED';
- $event['event_status_date'] = datetime_convert();
- $event['event_percent'] = 100;
- $event['event_sequence'] = $event['event_sequence'] + 1;
- $event['edited'] = datetime_convert();
- }
- $x = event_store_event($event);
- if($x)
- $ret['success'] = true;
- }
- json_return_and_die($ret);
- }
-
- if(argc() == 2 && argv(1) === 'new') {
- $text = escape_tags(trim($_REQUEST['summary']));
- if(! $text)
- return array('success' => false);
- $event = array();
- $event['account'] = $channel['channel_account_id'];
- $event['uid'] = $channel['channel_id'];
- $event['event_xchan'] = $channel['channel_hash'];
- $event['type'] = 'task';
- $event['nofinish'] = true;
- $event['created'] = $event['edited'] = $event['start'] = datetime_convert();
- $event['adjust'] = 1;
- $event['allow_cid'] = '<' . $channel['channel_hash'] . '>';
- $event['summary'] = escape_tags($_REQUEST['summary']);
- $x = event_store_event($event);
- if($x)
- $x['success'] = true;
- else
- $x = array('success' => false);
- json_return_and_die($x);
- }
-
-
-}
-
-
-
-
-
-function tasks_content(&$a) {
-
- if(! local_channel())
- return;
-
-
- return '';
-} \ No newline at end of file
diff --git a/mod/thing.php b/mod/thing.php
deleted file mode 100644
index 44e9d9e2e..000000000
--- a/mod/thing.php
+++ /dev/null
@@ -1,362 +0,0 @@
-<?php
-/**
- * @file mod/thing.php
- * @brief
- */
-
-require_once('include/items.php');
-require_once('include/security.php');
-require_once('include/contact_selectors.php');
-require_once('include/acl_selectors.php');
-
-function thing_init(&$a) {
-
- if(! local_channel())
- return;
-
- $channel = App::get_channel();
-
- $term_hash = (($_REQUEST['term_hash']) ? $_REQUEST['term_hash'] : '');
-
- $name = escape_tags($_REQUEST['term']);
- $verb = escape_tags($_REQUEST['verb']);
- $activity = intval($_REQUEST['activity']);
- $profile_guid = escape_tags($_REQUEST['profile_assign']);
- $url = $_REQUEST['link'];
- $photo = $_REQUEST['img'];
-
- $hash = random_string();
-
- $verbs = obj_verbs();
-
- /**
- * verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants"
- * We use the first person form when creating an activity, but the third person for use in activities
- * @FIXME There is no accounting for verb gender for languages where this is significant. We may eventually
- * require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module.
- */
-
- $translated_verb = $verbs[$verb][1];
-
- /*
- * The site administrator can do things that normals cannot.
- * This is restricted because it will likely cause
- * an activitystreams protocol violation and the activity might
- * choke in some other network and result in unnecessary
- * support requests. It isn't because we're trying to be heavy-handed
- * about what you can and can't do.
- */
-
- if(! $translated_verb) {
- if(is_site_admin())
- $translated_verb = $verb;
- }
-
- /*
- * Things, objects: We do not provide definite (a, an) or indefinite (the) articles or singular/plural designators
- * That needs to be specified in your thing. e.g. Mike has "a carrot", Greg wants "balls", Bob likes "the Boston Red Sox".
- */
-
- /*
- * Future work on this module might produce more complex activities with targets, e.g. Phillip likes Karen's moustache
- * and to describe other non-thing objects like channels, such as Karl wants Susan - where Susan represents a channel profile.
- */
-
- if((! $name) || (! $translated_verb))
- return;
-
- $acl = new Zotlabs\Access\AccessList($channel);
-
- if(array_key_exists('contact_allow',$_REQUEST)
- || array_key_exists('group_allow',$_REQUEST)
- || array_key_exists('contact_deny',$_REQUEST)
- || array_key_exists('group_deny',$_REQUEST)) {
- $acl->set_from_array($_REQUEST);
- }
-
- $x = $acl->get();
-
- if($term_hash) {
- $t = q("select * from obj where obj_obj = '%s' and obj_channel = %d limit 1",
- dbesc($term_hash),
- intval(local_channel())
- );
- if(! $t) {
- notice( t('Item not found.') . EOL);
- return;
- }
- $orig_record = $t[0];
- if($photo != $orig_record['obj_imgurl']) {
- $arr = import_xchan_photo($photo,get_observer_hash(),true);
- $local_photo = $arr[0];
- $local_photo_type = $arr[3];
- }
- else
- $local_photo = $orig_record['obj_imgurl'];
-
- $r = q("update obj set obj_term = '%s', obj_url = '%s', obj_imgurl = '%s', obj_edited = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where obj_obj = '%s' and obj_channel = %d ",
- dbesc($name),
- dbesc(($url) ? $url : z_root() . '/thing/' . $term_hash),
- dbesc($local_photo),
- dbesc(datetime_convert()),
- dbesc($x['allow_cid']),
- dbesc($x['allow_gid']),
- dbesc($x['deny_cid']),
- dbesc($x['deny_gid']),
- dbesc($term_hash),
- intval(local_channel())
- );
-
- info( t('Thing updated') . EOL);
-
- $r = q("select * from obj where obj_channel = %d and obj_obj = '%s' limit 1",
- intval(local_channel()),
- dbesc($term_hash)
- );
- if($r) {
- build_sync_packet(0, array('obj' => $r));
- }
-
- return;
- }
-
- $sql = (($profile_guid) ? " and profile_guid = '" . dbesc($profile_guid) . "' " : " and is_default = 1 ");
- $p = q("select profile_guid, is_default from profile where uid = %d $sql limit 1",
- intval(local_channel())
- );
-
- if($p)
- $profile = $p[0];
- else
- return;
-
- $local_photo = null;
-
- if($photo) {
- $arr = import_xchan_photo($photo,get_observer_hash(),true);
- $local_photo = $arr[0];
- $local_photo_type = $arr[3];
- }
-
- $created = datetime_convert();
- $url = (($url) ? $url : z_root() . '/thing/' . $hash);
-
- $r = q("insert into obj ( obj_page, obj_verb, obj_type, obj_channel, obj_obj, obj_term, obj_url, obj_imgurl, obj_created, obj_edited, allow_cid, allow_gid, deny_cid, deny_gid ) values ('%s','%s', %d, %d, '%s','%s','%s','%s','%s','%s','%s','%s','%s','%s') ",
- dbesc($profile['profile_guid']),
- dbesc($verb),
- intval(TERM_OBJ_THING),
- intval(local_channel()),
- dbesc($hash),
- dbesc($name),
- dbesc($url),
- dbesc(($photo) ? $local_photo : ''),
- dbesc($created),
- dbesc($created),
- dbesc($x['allow_cid']),
- dbesc($x['allow_gid']),
- dbesc($x['deny_cid']),
- dbesc($x['deny_gid'])
- );
-
- if(! $r) {
- notice( t('Object store: failed'));
- return;
- }
-
- info( t('Thing added'));
-
- $r = q("select * from obj where obj_channel = %d and obj_obj = '%s' limit 1",
- intval(local_channel()),
- dbesc($hash)
- );
- if($r) {
- build_sync_packet(0, array('obj' => $r));
- }
-
- if($activity) {
- $arr = array();
- $links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $url));
- if($local_photo)
- $links[] = array('rel' => 'photo', 'type' => $local_photo_type, 'href' => $local_photo);
-
- $objtype = ACTIVITY_OBJ_THING;
-
- $obj = json_encode(array(
- 'type' => $objtype,
- 'id' => $url,
- 'link' => $links,
- 'title' => $name,
- 'content' => $name
- ));
-
- $bodyverb = str_replace('OBJ: ', '',t('OBJ: %1$s %2$s %3$s'));
-
- $arr['owner_xchan'] = $channel['channel_hash'];
- $arr['author_xchan'] = $channel['channel_hash'];
-
- $arr['item_origin'] = 1;
- $arr['item_wall'] = 1;
- $arr['item_thread_top'] = 1;
-
- $ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]';
- $plink = '[zrl=' . $url . ']' . $name . '[/zrl]';
-
- $arr['body'] = sprintf( $bodyverb, $ulink, $translated_verb, $plink );
-
- if($local_photo)
- $arr['body'] .= "\n\n[zmg]" . $local_photo . "[/zmg]";
-
- $arr['verb'] = $verb;
- $arr['obj_type'] = $objtype;
- $arr['object'] = $obj;
-
- if(! $profile['is_default']) {
- $arr['item_private'] = true;
- $str = '';
- $r = q("select abook_xchan from abook where abook_channel = %d and abook_profile = '%s'",
- intval(local_channel()),
- dbesc($profile_guid)
- );
- if($r) {
- $arr['allow_cid'] = '';
- foreach($r as $rr)
- $arr['allow_cid'] .= '<' . $rr['abook_xchan'] . '>';
- }
- else
- $arr['allow_cid'] = '<' . get_observer_hash() . '>';
- }
-
- $ret = post_activity_item($arr);
- }
-}
-
-
-function thing_content(&$a) {
-
- // @FIXME one problem with things is we can't share them unless we provide the channel in the url
- // so we can definitively lookup the owner.
-
- if(argc() == 2) {
-
- $r = q("select obj_channel from obj where obj_type = %d and obj_obj = '%s' limit 1",
- intval(TERM_OBJ_THING),
- dbesc(argv(1))
- );
- if($r)
- $sql_extra = permissions_sql($r[0]['obj_channel']);
-
- $r = q("select * from obj where obj_type = %d and obj_obj = '%s' $sql_extra limit 1",
- intval(TERM_OBJ_THING),
- dbesc(argv(1))
- );
-
- if($r) {
- return replace_macros(get_markup_template('show_thing.tpl'), array(
- '$header' => t('Show Thing'),
- '$edit' => t('Edit'),
- '$delete' => t('Delete'),
- '$canedit' => ((local_channel() && local_channel() == $r[0]['obj_channel']) ? true : false),
- '$thing' => $r[0] ));
- }
- else {
- notice( t('item not found.') . EOL);
- return;
- }
- }
-
- $channel = App::get_channel();
-
- if(! (local_channel() && $channel)) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- $acl = new Zotlabs\Access\AccessList($channel);
- $channel_acl = $acl->get();
-
- $lockstate = (($acl->is_private()) ? 'lock' : 'unlock');
-
- $thing_hash = '';
-
- if(argc() == 3 && argv(1) === 'edit') {
- $thing_hash = argv(2);
-
- $r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1",
- intval(TERM_OBJ_THING),
- dbesc($thing_hash)
- );
-
- if((! $r) || ($r[0]['obj_channel'] != local_channel())) {
- notice( t('Permission denied.') . EOL);
- return '';
- }
-
- $o .= replace_macros(get_markup_template('thing_edit.tpl'),array(
- '$thing_hdr' => t('Edit Thing'),
- '$multiprof' => feature_enabled(local_channel(),'multi_profiles'),
- '$profile_lbl' => t('Select a profile'),
- '$profile_select' => contact_profile_assign($r[0]['obj_page']),
- '$verb_lbl' => $channel['channel_name'],
- '$verb_select' => obj_verb_selector($r[0]['obj_verb']),
- '$activity' => array('activity',t('Post an activity'),true,t('Only sends to viewers of the applicable profile')),
- '$thing_hash' => $thing_hash,
- '$thing_lbl' => t('Name of thing e.g. something'),
- '$thething' => $r[0]['obj_term'],
- '$url_lbl' => t('URL of thing (optional)'),
- '$theurl' => $r[0]['obj_url'],
- '$img_lbl' => t('URL for photo of thing (optional)'),
- '$imgurl' => $r[0]['obj_imgurl'],
- '$permissions' => t('Permissions'),
- '$aclselect' => populate_acl($channel_acl,false),
- '$lockstate' => $lockstate,
- '$submit' => t('Submit')
- ));
-
- return $o;
- }
-
- if(argc() == 3 && argv(1) === 'drop') {
- $thing_hash = argv(2);
-
- $r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1",
- intval(TERM_OBJ_THING),
- dbesc($thing_hash)
- );
-
- if((! $r) || ($r[0]['obj_channel'] != local_channel())) {
- notice( t('Permission denied.') . EOL);
- return '';
- }
-
- $x = q("delete from obj where obj_obj = '%s' and obj_type = %d and obj_channel = %d",
- dbesc($thing_hash),
- intval(TERM_OBJ_THING),
- intval(local_channel())
- );
-
- $r[0]['obj_deleted'] = 1;
-
- build_sync_packet(0,array('obj' => $r));
-
- return $o;
- }
-
- $o .= replace_macros(get_markup_template('thing_input.tpl'),array(
- '$thing_hdr' => t('Add Thing to your Profile'),
- '$multiprof' => feature_enabled(local_channel(),'multi_profiles'),
- '$profile_lbl' => t('Select a profile'),
- '$profile_select' => contact_profile_assign(''),
- '$verb_lbl' => $channel['channel_name'],
- '$activity' => array('activity',t('Post an activity'),((array_key_exists('activity',$_REQUEST)) ? $_REQUEST['activity'] : true),t('Only sends to viewers of the applicable profile')),
- '$verb_select' => obj_verb_selector(),
- '$thing_lbl' => t('Name of thing e.g. something'),
- '$url_lbl' => t('URL of thing (optional)'),
- '$img_lbl' => t('URL for photo of thing (optional)'),
- '$permissions' => t('Permissions'),
- '$aclselect' => populate_acl($channel_acl,false),
- '$lockstate' => $lockstate,
- '$submit' => t('Submit')
- ));
-
- return $o;
-}
diff --git a/mod/toggle_mobile.php b/mod/toggle_mobile.php
deleted file mode 100644
index 918c4aad6..000000000
--- a/mod/toggle_mobile.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-function toggle_mobile_init(&$a) {
-
- if(isset($_GET['off']))
- $_SESSION['show_mobile'] = false;
- else
- $_SESSION['show_mobile'] = true;
-
- if(isset($_GET['address']))
- $address = $_GET['address'];
- else
- $address = z_root();
-
- goaway($address);
-}
-
diff --git a/mod/toggle_safesearch.php b/mod/toggle_safesearch.php
deleted file mode 100644
index 3c800c4f3..000000000
--- a/mod/toggle_safesearch.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-function toggle_safesearch_init(&$a) {
-
-$observer = get_observer_hash();
-if (! $observer)
- return;
-
-if($observer)
- $safe_mode = get_xconfig($observer,'directory','safe_mode');
-if ($safe_mode == '')
- set_xconfig($observer,'directory','safe_mode', '0');
-elseif($safe_mode == '0')
- set_xconfig($observer,'directory','safe_mode', '1');
-elseif($safe_mode == '1')
- set_xconfig($observer,'directory','safe_mode', '0');
-
-if(isset($_GET['address']))
- $address = $_GET['address'];
-else
- $address = z_root() . '/directory';
-
- goaway($address);
-}
-
diff --git a/mod/uexport.php b/mod/uexport.php
deleted file mode 100644
index 4a16903f8..000000000
--- a/mod/uexport.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-function uexport_init(&$a) {
- if(! local_channel())
- killme();
-
- if(argc() > 1) {
- $channel = App::get_channel();
-
- require_once('include/identity.php');
-
- if(argc() > 1 && intval(argv(1)) > 1900) {
- $year = intval(argv(1));
- }
-
- if(argc() > 2 && intval(argv(2)) > 0 && intval(argv(2)) <= 12) {
- $month = intval(argv(2));
- }
-
- header('content-type: application/octet_stream');
- header('content-disposition: attachment; filename="' . $channel['channel_address'] . (($year) ? '-' . $year : '') . (($month) ? '-' . $month : '') . '.json"' );
-
- if($year) {
- echo json_encode(identity_export_year(local_channel(),$year,$month));
- killme();
- }
-
- if(argc() > 1 && argv(1) === 'basic') {
- echo json_encode(identity_basic_export(local_channel()));
- killme();
- }
-
- // FIXME - this basically doesn't work in the wild with a channel more than a few months old due to memory and execution time limits.
- // It probably needs to be built at the CLI and offered to download as a tarball. Maybe stored in the members dav.
-
- if(argc() > 1 && argv(1) === 'complete') {
- echo json_encode(identity_basic_export(local_channel(),true));
- killme();
- }
- }
-}
-
-function uexport_content(&$a) {
-
- $y = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
-
- $yearurl = z_root() . '/uexport/' . $y;
- $janurl = z_root() . '/uexport/' . $y . '/1';
- $impurl = '/import_items';
- $o = replace_macros(get_markup_template('uexport.tpl'), array(
- '$title' => t('Export Channel'),
- '$basictitle' => t('Export Channel'),
- '$basic' => t('Export your basic channel information to a file. This acts as a backup of your connections, permissions, profile and basic data, which can be used to import your data to a new server hub, but does not contain your content.'),
- '$fulltitle' => t('Export Content'),
- '$full' => t('Export your channel information and recent content to a JSON backup that can be restored or imported to another server hub. This backs up all of your connections, permissions, profile data and several months of posts. This file may be VERY large. Please be patient - it may take several minutes for this download to begin.'),
- '$by_year' => t('Export your posts from a given year.'),
-
- '$extra' => t('You may also export your posts and conversations for a particular year or month. Adjust the date in your browser location bar to select other dates. If the export fails (possibly due to memory exhaustion on your server hub), please try again selecting a more limited date range.'),
- '$extra2' => sprintf( t('To select all posts for a given year, such as this year, visit <a href="%1$s">%2$s</a>'),$yearurl,$yearurl),
- '$extra3' => sprintf( t('To select all posts for a given month, such as January of this year, visit <a href="%1$s">%2$s</a>'),$janurl,$janurl),
- '$extra4' => sprintf( t('These content files may be imported or restored by visiting <a href="%1$s">%2$s</a> on any site containing your channel. For best results please import or restore these in date order (oldest first).'),$impurl,$impurl)
-
- ));
-return $o;
-}
diff --git a/mod/update_display.php b/mod/update_display.php
deleted file mode 100644
index 52903bb8c..000000000
--- a/mod/update_display.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-// See update_profile.php for documentation
-
-require_once('mod/display.php');
-require_once('include/group.php');
-
-function update_display_content(&$a) {
-
- $profile_uid = intval($_GET['p']);
- if(! $profile_uid)
- $profile_uid = (-1);
- $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
- header("Content-type: text/html");
- echo "<!DOCTYPE html><html><body>\r\n";
- echo (($_GET['msie'] == 1) ? '<div>' : '<section>');
-
-
- $text = display_content($a,$profile_uid, $load);
- $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
- $replace = "<img\${1} dst=\"\${2}\"";
-// $text = preg_replace($pattern, $replace, $text);
-/*
- if(! $load) {
- $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
- $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
- $text = preg_replace($pattern, $replace, $text);
- }
-*/
- echo str_replace("\t",' ',$text);
- echo (($_GET['msie'] == 1) ? '</div>' : '</section>');
- echo "</body></html>\r\n";
-// logger('update_display: ' . $text);
- killme();
-
-}
diff --git a/mod/update_home.php b/mod/update_home.php
deleted file mode 100644
index 4a8000bdb..000000000
--- a/mod/update_home.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-// See update_profile.php for documentation
-
-require_once('mod/home.php');
-
-function update_home_content(&$a) {
-
- $profile_uid = ((intval($_GET['p'])) ? intval($_GET['p']) : (-1));
- $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
- header("Content-type: text/html");
- echo "<!DOCTYPE html><html><body>\r\n";
- echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '<div>' : '<section>');
-
- $text = home_content($a,$profile_uid, $load);
- $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
- $replace = "<img\${1} dst=\"\${2}\"";
-// $text = preg_replace($pattern, $replace, $text);
-/*
- if(! $load) {
- $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
- $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
- $text = preg_replace($pattern, $replace, $text);
- }
-*/
- echo str_replace("\t",' ',$text);
- echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '</div>' : '</section>');
- echo "</body></html>\r\n";
-// logger('update_home: ' . $text);
- killme();
-
-} \ No newline at end of file
diff --git a/mod/update_network.php b/mod/update_network.php
deleted file mode 100644
index 03c12312c..000000000
--- a/mod/update_network.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-// See update_profile.php for documentation
-
-require_once('mod/network.php');
-require_once('include/group.php');
-
-function update_network_content(&$a) {
-
- $profile_uid = intval($_GET['p']);
- $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
- header("Content-type: text/html");
- echo "<!DOCTYPE html><html><body>\r\n";
- echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '<div>' : '<section>');
-
-
- $text = network_content($a,$profile_uid, $load);
- $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
- $replace = "<img\${1} dst=\"\${2}\"";
-// $text = preg_replace($pattern, $replace, $text);
-/*
- if(! $load) {
- $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
- $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
- $text = preg_replace($pattern, $replace, $text);
- }
-*/
- echo str_replace("\t",' ',$text);
- echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '</div>' : '</section>');
- echo "</body></html>\r\n";
-// logger('update_network: ' . $text);
- killme();
-
-} \ No newline at end of file
diff --git a/mod/update_public.php b/mod/update_public.php
deleted file mode 100644
index fcec792f6..000000000
--- a/mod/update_public.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-// See update_profile.php for documentation
-
-require_once('mod/public.php');
-
-function update_public_content(&$a) {
-
- $profile_uid = ((intval($_GET['p'])) ? intval($_GET['p']) : (-1));
- $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
- header("Content-type: text/html");
- echo "<!DOCTYPE html><html><body>\r\n";
- echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '<div>' : '<section>');
-
- $text = public_content($a,$profile_uid, $load);
- $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
- $replace = "<img\${1} dst=\"\${2}\"";
-// $text = preg_replace($pattern, $replace, $text);
-/*
- if(! $load) {
- $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
- $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
- $text = preg_replace($pattern, $replace, $text);
- }
-*/
- echo str_replace("\t",' ',$text);
- echo ((array_key_exists('msie',$_GET) && $_GET['msie'] == 1) ? '</div>' : '</section>');
- echo "</body></html>\r\n";
- killme();
-
-} \ No newline at end of file
diff --git a/mod/update_search.php b/mod/update_search.php
deleted file mode 100644
index 25bcffcb6..000000000
--- a/mod/update_search.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-/**
- * Module: update_profile
- * Purpose: AJAX synchronisation of search page
- *
- */
-
-
-require_once('mod/search.php');
-
-function update_search_content(&$a) {
-
- $profile_uid = intval($_GET['p']);
- if(! $profile_uid)
- $profile_uid = (-1);
-
- $load = (((argc() > 1) && (argv(1) == 'load')) ? 1 : 0);
-
- header("Content-type: text/html");
- echo "<!DOCTYPE html><html><body>\r\n";
-
- /**
- * We can remove this hack once Internet Explorer recognises HTML5 natively
- */
-
- echo (($_GET['msie'] == 1) ? '<div>' : '<section>');
-
- /**
- *
- * Grab the page inner contents by calling the content function from the profile module directly,
- * but move any image src attributes to another attribute name. This is because
- * some browsers will prefetch all the images for the page even if we don't need them.
- * The only ones we need to fetch are those for new page additions, which we'll discover
- * on the client side and then swap the image back.
- *
- */
-
- $text = search_content($a,$profile_uid,$load);
-
- $pattern = "/<img([^>]*) src=\"([^\"]*)\"/";
- $replace = "<img\${1} dst=\"\${2}\"";
-// $text = preg_replace($pattern, $replace, $text);
-/*
- if(! $load) {
- $replace = '<br />' . t('[Embedded content - reload page to view]') . '<br />';
- $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
- $text = preg_replace($pattern, $replace, $text);
- }
-*/
- /**
- * reportedly some versions of MSIE don't handle tabs in XMLHttpRequest documents very well
- */
-
- echo str_replace("\t",' ',$text);
- echo (($_GET['msie'] == 1) ? '</div>' : '</section>');
- echo "</body></html>\r\n";
- killme();
-
-} \ No newline at end of file
diff --git a/mod/view.php b/mod/view.php
deleted file mode 100644
index f18646cb9..000000000
--- a/mod/view.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-/**
- * load view/theme/$current_theme/style.php with Hubzilla context
- */
-
-function view_init($a){
-
- header("Content-Type: text/css");
-
- $theme = argv(2);
- $THEMEPATH = "view/theme/$theme";
- if(file_exists("view/theme/$theme/php/style.php"))
- require_once("view/theme/$theme/php/style.php");
- killme();
-}
diff --git a/mod/viewconnections.php b/mod/viewconnections.php
deleted file mode 100644
index 6e0daab6e..000000000
--- a/mod/viewconnections.php
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-require_once('include/contact_selectors.php');
-require_once('include/Contact.php');
-
-function viewconnections_init(&$a) {
-
- if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
- return;
- }
- if(argc() > 1)
- profile_load($a,argv(1));
-}
-
-function viewconnections_content(&$a) {
-
- if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
- notice( t('Public access denied.') . EOL);
- return;
- }
-
- if(((! count(App::$profile)) || (App::$profile['hide_friends']))) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- if(! perm_is_allowed(App::$profile['uid'], get_observer_hash(),'view_contacts')) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- if(! $_REQUEST['aj'])
- $_SESSION['return_url'] = App::$query_string;
-
-
- $is_owner = ((local_channel() && local_channel() == App::$profile['uid']) ? true : false);
-
- $abook_flags = " and abook_pending = 0 and abook_self = 0 ";
- $sql_extra = '';
-
- if(! $is_owner) {
- $abook_flags = " and abook_hidden = 0 ";
- $sql_extra = " and xchan_hidden = 0 ";
- }
-
- $r = q("SELECT count(*) as total FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra ",
- intval(App::$profile['uid'])
- );
- if($r) {
- App::set_pager_total($r[0]['total']);
- }
-
- $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra order by xchan_name LIMIT %d OFFSET %d ",
- intval(App::$profile['uid']),
- intval(App::$pager['itemspage']),
- intval(App::$pager['start'])
- );
-
- if((! $r) && (! $_REQUEST['aj'])) {
- info( t('No connections.') . EOL );
- return $o;
- }
-
- $contacts = array();
-
- foreach($r as $rr) {
-
- $url = chanlink_url($rr['xchan_url']);
- if($url) {
- $contacts[] = array(
- 'id' => $rr['abook_id'],
- 'archived' => (intval($rr['abook_archived']) ? true : false),
- 'img_hover' => sprintf( t('Visit %s\'s profile [%s]'), $rr['xchan_name'], $rr['xchan_url']),
- 'thumb' => $rr['xchan_photo_m'],
- 'name' => substr($rr['xchan_name'],0,20),
- 'username' => $rr['xchan_addr'],
- 'link' => $url,
- 'sparkle' => '',
- 'itemurl' => $rr['url'],
- 'network' => '',
- );
- }
- }
-
-
- if($_REQUEST['aj']) {
- if($contacts) {
- $o = replace_macros(get_markup_template('viewcontactsajax.tpl'),array(
- '$contacts' => $contacts
- ));
- }
- 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>";
- $tpl = get_markup_template("viewcontact_template.tpl");
- $o .= replace_macros($tpl, array(
- '$title' => t('View Connections'),
- '$contacts' => $contacts,
-// '$paginate' => paginate($a),
- ));
- }
-
- if(! $contacts)
- $o .= '<div id="content-complete"></div>';
-
- return $o;
-}
diff --git a/mod/viewsrc.php b/mod/viewsrc.php
deleted file mode 100644
index a4efd1214..000000000
--- a/mod/viewsrc.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-
-function viewsrc_content(&$a) {
-
- $o = '';
-
- $sys = get_sys_channel();
-
- $item_id = ((argc() > 1) ? intval(argv(1)) : 0);
- $json = ((argc() > 2 && argv(2) === 'json') ? true : false);
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- }
-
-
- if(! $item_id) {
- App::$error = 404;
- notice( t('Item not found.') . EOL);
- }
-
- $item_normal = item_normal();
-
- if(local_channel() && $item_id) {
- $r = q("select id, item_flags, item_obscured, body from item where uid in (%d , %d) and id = %d $item_normal limit 1",
- intval(local_channel()),
- intval($sys['channel_id']),
- intval($item_id)
- );
-
- if($r) {
- if(intval($r[0]['item_obscured']))
- $r[0]['body'] = crypto_unencapsulate(json_decode($r[0]['body'],true),get_config('system','prvkey'));
- $o = (($json) ? json_encode($r[0]['body']) : str_replace("\n",'<br />',$r[0]['body']));
- }
- }
-
- if(is_ajax()) {
- print '<div><i class="icon-pencil"> ' . t('Source of Item') . ' ' . $r[0]['id'] . '</i></div>';
- echo $o;
- killme();
- }
-
- return $o;
-}
-
diff --git a/mod/wall_attach.php b/mod/wall_attach.php
deleted file mode 100644
index 7f054705f..000000000
--- a/mod/wall_attach.php
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-
-require_once('include/attach.php');
-require_once('include/identity.php');
-require_once('include/photos.php');
-
-function wall_attach_post(&$a) {
-
- $using_api = false;
-
- if(App::$data['api_info'] && array_key_exists('media',$_FILES)) {
- $using_api = true;
- $user_info = App::$data['api_info'];
- $nick = $user_info['screen_name'];
- $channel = get_channel_by_nick($user_info['screen_name']);
- }
- elseif(argc() > 1)
- $channel = get_channel_by_nick(argv(1));
-
- if(! $channel)
- killme();
-
- $observer = App::get_observer();
-
-
- $def_album = get_pconfig($channel['channel_id'],'system','photo_path');
- $def_attach = get_pconfig($channel['channel_id'],'system','attach_path');
-
- $r = attach_store($channel,(($observer) ? $observer['xchan_hash'] : ''),'', array('source' => 'editor', 'visible' => 0, 'album' => $def_album, 'directory' => $def_attach, 'allow_cid' => '<' . $channel['channel_hash'] . '>'));
-
- if(! $r['success']) {
- notice( $r['message'] . EOL);
- killme();
- }
-
- if(intval($r['data']['is_photo'])) {
- $s = "\n\n" . $r['body'] . "\n\n";
- }
- else {
- $s = "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n";
- }
-
- if($using_api)
- return $s;
-
- echo $s;
- killme();
-
-}
diff --git a/mod/wall_upload.php b/mod/wall_upload.php
deleted file mode 100644
index 54e2f8526..000000000
--- a/mod/wall_upload.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-require_once('include/photo/photo_driver.php');
-require_once('include/identity.php');
-require_once('include/photos.php');
-
-
-
-function wall_upload_post(&$a) {
-
-
- $using_api = ((x($_FILES,'media')) ? true : false);
-
- if($using_api) {
- require_once('include/api.php');
- $user_info = api_get_user($a);
- $nick = $user_info['screen_name'];
- }
- else {
- if(argc() > 1)
- $nick = argv(1);
- }
-
- $channel = (($nick) ? get_channel_by_nick($nick) : false);
-
- if(! $channel) {
- if($using_api)
- return;
- notice( t('Channel not found.') . EOL);
- killme();
- }
-
- $observer = App::get_observer();
-
- $args = array( 'source' => 'editor', 'visible' => 0, 'contact_allow' => array($channel['channel_hash']));
-
- $ret = photo_upload($channel,$observer,$args);
-
- if(! $ret['success']) {
- if($using_api)
- return;
- notice($ret['message']);
- killme();
- }
-
- if($using_api)
- return("\n\n" . $ret['body'] . "\n\n");
- else
- echo "\n\n" . $ret['body'] . "\n\n";
- killme();
-}
diff --git a/mod/webfinger.php b/mod/webfinger.php
deleted file mode 100644
index e35767338..000000000
--- a/mod/webfinger.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-
-
-
-function webfinger_content(&$a) {
-
-
- $o .= '<h3>Webfinger Diagnostic</h3>';
-
- $o .= '<form action="webfinger" method="get">';
- $o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
- $o .= '<input type="submit" name="submit" value="Submit" /></form>';
-
- $o .= '<br /><br />';
-
- $old = false;
- if(x($_GET,'addr')) {
- $addr = trim($_GET['addr']);
-// if(strpos($addr,'@') !== false) {
- $res = webfinger_rfc7033($addr,true);
- if(! $res) {
- $res = old_webfinger($addr);
- $old = true;
- }
-// }
-// else {
-// if(function_exists('lrdd'))
-// $res = lrdd($addr);
-// }
-
- if($res && $old) {
- foreach($res as $r) {
- if($r['@attributes']['rel'] === 'http://microformats.org/profile/hcard') {
- $hcard = unamp($r['@attributes']['href']);
- require_once('library/HTML5/Parser.php');
- $res['vcard'] = scrape_vcard($hcard);
- break;
- }
- }
- }
-
-
- $o .= '<pre>';
- $o .= str_replace("\n",'<br />',print_r($res,true));
- $o .= '</pre>';
- }
- return $o;
-}
diff --git a/mod/webpages.php b/mod/webpages.php
deleted file mode 100644
index c20a147da..000000000
--- a/mod/webpages.php
+++ /dev/null
@@ -1,201 +0,0 @@
-<?php
-
-require_once('include/identity.php');
-require_once('include/conversation.php');
-require_once('include/acl_selectors.php');
-
-function webpages_init(&$a) {
-
- 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 webpages_content(&$a) {
-
- 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;
- }
-
- $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype'));
-
- if(! $mimetype) {
- $mimetype = 'choose';
- }
-
- $layout = (($_REQUEST['layout']) ? $_REQUEST['layout'] : get_pconfig($owner,'system','page_layout'));
- if(! $layout)
- $layout = 'choose';
-
- // 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 owner's.
- // This lets you post pages at other people's channels.
-
- if((! $channel) && ($uid) && ($uid == App::$profile_uid)) {
- $channel = App::get_channel();
- }
- if($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']
- );
- }
- else
- $channel_acl = array();
-
- $is_owner = ($uid && $uid == $owner);
- $o = profile_tabs($a, $is_owner, App::$profile['channel_address']);
-
- $x = array(
- 'webpage' => ITEM_TYPE_WEBPAGE,
- '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' => '',
- 'acl' => (($is_owner) ? populate_acl($channel_acl,false) : ''),
- 'showacl' => (($is_owner) ? true : false),
- 'visitor' => true,
- 'profile_uid' => intval($owner),
- 'mimetype' => $mimetype,
- 'layout' => $layout,
- '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);
-
- // Get a list of webpages. We can't display all them because endless scroll makes that unusable,
- // so just list titles and an edit link.
-
-
- /** @TODO - this should be replaced with pagelist_widget */
-
- $sql_extra = item_permissions_sql($owner);
-
- $r = q("select * from item_id left join item on item_id.iid = item.id
- where item_id.uid = %d and service = 'WEBPAGE' and item_type = %d $sql_extra order by item.created desc",
- intval($owner),
- intval(ITEM_TYPE_WEBPAGE)
- );
-
- $pages = null;
-
- if($r) {
- $pages = array();
- foreach($r as $rr) {
- unobscure($rr);
-
- $lockstate = (($rr['allow_cid'] || $rr['allow_gid'] || $rr['deny_cid'] || $rr['deny_gid']) ? 'lock' : 'unlock');
-
- $element_arr = array(
- 'type' => 'webpage',
- 'title' => $rr['title'],
- 'body' => $rr['body'],
- 'created' => $rr['created'],
- 'edited' => $rr['edited'],
- 'mimetype' => $rr['mimetype'],
- 'pagetitle' => $rr['sid'],
- 'mid' => $rr['mid'],
- 'layout_mid' => $rr['layout_mid']
- );
- $pages[$rr['iid']][] = array(
- 'url' => $rr['iid'],
- 'pagetitle' => $rr['sid'],
- 'title' => $rr['title'],
- 'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']),
- 'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited']),
- 'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]',
- 'lockstate' => $lockstate
- );
- }
- }
-
-
- //Build the base URL for edit links
- $url = z_root() . '/editwebpage/' . $which;
-
- $o .= replace_macros(get_markup_template('webpagelist.tpl'), array(
- '$listtitle' => t('Webpages'),
- '$baseurl' => $url,
- '$create' => t('Create'),
- '$edit' => t('Edit'),
- '$share' => t('Share'),
- '$delete' => t('Delete'),
- '$pages' => $pages,
- '$channel' => $which,
- '$editor' => $editor,
- '$view' => t('View'),
- '$preview' => t('Preview'),
- '$actions_txt' => t('Actions'),
- '$pagelink_txt' => t('Page Link'),
- '$title_txt' => t('Page Title'),
- '$created_txt' => t('Created'),
- '$edited_txt' => t('Edited')
- ));
-
- return $o;
-}
diff --git a/mod/wfinger.php b/mod/wfinger.php
deleted file mode 100644
index 445dbb349..000000000
--- a/mod/wfinger.php
+++ /dev/null
@@ -1,134 +0,0 @@
-<?php
-
-require_once('include/zot.php');
-
-function wfinger_init(&$a) {
-
- $result = array();
-
- $scheme = '';
-
- if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS'])
- $scheme = 'https';
- elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443))
- $scheme = 'https';
-
- $zot = intval($_REQUEST['zot']);
-
- if(($scheme !== 'https') && (! $zot)) {
- header($_SERVER["SERVER_PROTOCOL"] . ' ' . 500 . ' ' . 'Webfinger requires HTTPS');
- killme();
- }
-
-
- $resource = $_REQUEST['resource'];
- logger('webfinger: ' . $resource,LOGGER_DEBUG);
-
- $r = null;
-
- if($resource) {
-
- if(strpos($resource,'acct:') === 0) {
- $channel = str_replace('acct:','',$resource);
- if(strpos($channel,'@') !== false) {
- $host = substr($channel,strpos($channel,'@')+1);
- if(strcasecmp($host,App::get_hostname())) {
- goaway('https://' . $host . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=' . $zot : ''));
- }
- $channel = substr($channel,0,strpos($channel,'@'));
- }
- }
- if(strpos($resource,'http') === 0) {
- $channel = str_replace('~','',basename($resource));
- }
-
- $r = q("select * from channel left join xchan on channel_hash = xchan_hash
- where channel_address = '%s' limit 1",
- dbesc($channel)
- );
-
- }
-
- header('Access-Control-Allow-Origin: *');
-
-
- if($resource && $r) {
-
- $h = q("select hubloc_addr from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
- dbesc($r[0]['channel_hash'])
- );
-
- $result['subject'] = $resource;
-
- $aliases = array(
- z_root() . '/channel/' . $r[0]['channel_address'],
- z_root() . '/~' . $r[0]['channel_address']
- );
-
- if($h) {
- foreach($h as $hh) {
- $aliases[] = 'acct:' . $hh['hubloc_addr'];
- }
- }
-
- $result['aliases'] = array();
-
- $result['properties'] = array(
- 'http://webfinger.net/ns/name' => $r[0]['channel_name'],
- 'http://xmlns.com/foaf/0.1/name' => $r[0]['channel_name']
- );
-
- foreach($aliases as $alias)
- if($alias != $resource)
- $result['aliases'][] = $alias;
-
- $result['links'] = array(
-
- array(
- 'rel' => 'http://webfinger.net/rel/avatar',
- 'type' => $r[0]['xchan_photo_mimetype'],
- 'href' => $r[0]['xchan_photo_l']
- ),
-
- array(
- 'rel' => 'http://webfinger.net/rel/profile-page',
- 'href' => z_root() . '/profile/' . $r[0]['channel_address'],
- ),
-
- array(
- 'rel' => 'http://webfinger.net/rel/blog',
- 'href' => z_root() . '/channel/' . $r[0]['channel_address'],
- ),
-
- array(
- 'rel' => 'http://ostatus.org/schema/1.0/subscribe',
- 'template' => z_root() . '/follow/url={uri}',
- ),
-
- array(
- 'rel' => 'http://purl.org/zot/protocol',
- 'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r[0]['xchan_addr'],
- ),
-
- array(
- 'rel' => 'magic-public-key',
- 'href' => 'data:application/magic-public-key,' . salmon_key($r[0]['channel_pubkey']),
- )
- );
-
- if($zot) {
- // get a zotinfo packet and return it with webfinger
- $result['zot'] = zotinfo(array('address' => $r[0]['xchan_addr']));
- }
- }
- else {
- header($_SERVER["SERVER_PROTOCOL"] . ' ' . 400 . ' ' . 'Bad Request');
- killme();
- }
-
- $arr = array('channel' => $r[0], 'request' => $_REQUEST, 'result' => $result);
- call_hooks('webfinger',$arr);
-
- json_return_and_die($arr['result'],'application/jrd+json');
-
-}
diff --git a/mod/xchan.php b/mod/xchan.php
deleted file mode 100644
index 69fbdb77d..000000000
--- a/mod/xchan.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-
-function xchan_content(&$a) {
-
- $o = '<h3>' . t('Xchan Lookup') . '</h3>';
-
- $o .= '<form action="xchan" method="get">';
- $o .= t('Lookup xchan beginning with (or webbie): ');
- $o .= '<input type="text" style="width:250px;" name="addr" value="' . $_GET['addr'] .'">';
- $o .= '<input type="submit" name="submit" value="' . t('Submit') .'"></form>';
- $o .= '<br><br>';
-
- if(x($_GET, 'addr')) {
- $addr = trim($_GET['addr']);
-
- $r = q("select * from xchan where xchan_hash like '%s%%' or xchan_addr = '%s' group by xchan_hash",
- dbesc($addr),
- dbesc($addr)
- );
-
- if($r) {
- foreach($r as $rr) {
- $o .= str_replace(array("\n", " "), array("<br>", "&nbsp;"), print_r($rr, true)) . EOL;
-
- $s = q("select * from hubloc where hubloc_hash like '%s'",
- dbesc($r[0]['xchan_hash'])
- );
-
- if($s) {
- foreach($s as $rrr)
- $o .= str_replace(array("\n", " "), array("<br>", "&nbsp;"), print_r($rrr, true)) . EOL;
- }
- }
- }
- else
- notice( t('Not found.') . EOL);
-
- }
- return $o;
-}
diff --git a/mod/xpoco.php b/mod/xpoco.php
deleted file mode 100644
index 560966750..000000000
--- a/mod/xpoco.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-
-require_once('include/socgraph.php');
-
-function xpoco_init(&$a) {
- poco($a,true);
-}
diff --git a/mod/xrd.php b/mod/xrd.php
deleted file mode 100644
index 463cda662..000000000
--- a/mod/xrd.php
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-
-require_once('include/crypto.php');
-
-function xrd_init(&$a) {
-
- $uri = urldecode(notags(trim($_GET['uri'])));
- logger('xrd: ' . $uri,LOGGER_DEBUG);
-
- $resource = $uri;
-
- if(substr($uri,0,4) === 'http') {
- $uri = str_replace('~','',$uri);
- $name = basename($uri);
- }
- else {
- $local = str_replace('acct:', '', $uri);
- if(substr($local,0,2) == '//')
- $local = substr($local,2);
-
- $name = substr($local,0,strpos($local,'@'));
- }
-
- $r = q("SELECT * FROM channel WHERE channel_address = '%s' LIMIT 1",
- dbesc($name)
- );
- if(! $r)
- killme();
-
- $dspr = replace_macros(get_markup_template('xrd_diaspora.tpl'),array(
- '$baseurl' => z_root(),
- '$dspr_guid' => $r[0]['channel_guid'] . str_replace('.','',App::get_hostname()),
- '$dspr_key' => base64_encode(pemtorsa($r[0]['channel_pubkey']))
- ));
-
- $salmon_key = salmon_key($r[0]['channel_pubkey']);
-
- header('Access-Control-Allow-Origin: *');
- header("Content-type: application/xrd+xml");
-
-
- $aliases = array('acct:' . $r[0]['channel_address'] . '@' . App::get_hostname(), z_root() . '/channel/' . $r[0]['channel_address'], z_root() . '/~' . $r[0]['channel_address']);
-
- for($x = 0; $x < count($aliases); $x ++) {
- if($aliases[$x] === $resource)
- unset($aliases[$x]);
- }
-
-
- $o = replace_macros(get_markup_template('xrd_person.tpl'), array(
- '$nick' => $r[0]['channel_address'],
- '$accturi' => $resource,
- '$aliases' => $aliases,
- '$profile_url' => z_root() . '/channel/' . $r[0]['channel_address'],
- '$hcard_url' => z_root() . '/hcard/' . $r[0]['channel_address'],
- '$atom' => z_root() . '/feed/' . $r[0]['channel_address'],
- '$zot_post' => z_root() . '/post/' . $r[0]['channel_address'],
- '$poco_url' => z_root() . '/poco/' . $r[0]['channel_address'],
- '$photo' => z_root() . '/photo/profile/l/' . $r[0]['channel_id'],
- '$dspr' => $dspr,
-// '$salmon' => z_root() . '/salmon/' . $r[0]['channel_address'],
-// '$salmen' => z_root() . '/salmon/' . $r[0]['channel_address'] . '/mention',
- '$modexp' => 'data:application/magic-public-key,' . $salmon_key,
- '$subscribe' => z_root() . '/follow?url={uri}',
- '$bigkey' => salmon_key($r[0]['channel_pubkey'])
- ));
-
-
- $arr = array('user' => $r[0], 'xml' => $o);
- call_hooks('personal_xrd', $arr);
-
- echo $arr['xml'];
- killme();
-
-}
diff --git a/mod/xref.php b/mod/xref.php
deleted file mode 100644
index 95cc22aa7..000000000
--- a/mod/xref.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-function xref_init(&$a) {
- // Sets a referral URL using an xchan directly
- // Link format: example.com/xref/[xchan]/[TargetURL]
- // Target URL is optional.
- // Cookie lasts 24 hours to survive a browser restart. Contains no personal
- // information at all - just somebody else's xchan.
- $referrer = argv(1);
- $expire=time()+60*60*2;
- $path = 'xref';
- setcookie($path, $referrer, $expire, "/");
- $url = '';
-
- if (argc() > 2)
- $url = argv(2);
-
- goaway (z_root() . '/' . $url);
-
-}
diff --git a/mod/zfinger.php b/mod/zfinger.php
deleted file mode 100644
index fff7c9e1b..000000000
--- a/mod/zfinger.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-function zfinger_init(&$a) {
-
- require_once('include/zot.php');
- require_once('include/crypto.php');
-
-
- $x = zotinfo($_REQUEST);
- json_return_and_die($x);
-
-}
diff --git a/mod/zotfeed.php b/mod/zotfeed.php
deleted file mode 100644
index 5041532ae..000000000
--- a/mod/zotfeed.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-require_once('include/items.php');
-require_once('include/zot.php');
-
-function zotfeed_init(&$a) {
-
- $result = array('success' => false);
-
- $mindate = (($_REQUEST['mindate']) ? datetime_convert('UTC','UTC',$_REQUEST['mindate']) : '');
- if(! $mindate)
- $mindate = datetime_convert('UTC','UTC', 'now - 14 days');
-
- if(get_config('system','block_public') && (! get_account_id()) && (! remote_channel())) {
- $result['message'] = 'Public access denied';
- json_return_and_die($result);
- }
-
- $observer = App::get_observer();
-
-
- $channel_address = ((argc() > 1) ? argv(1) : '');
- if($channel_address) {
- $r = q("select channel_id, channel_name from channel where channel_address = '%s' and channel_removed = 0 limit 1",
- dbesc(argv(1))
- );
- }
- else {
- $x = get_sys_channel();
- if($x)
- $r = array($x);
- $mindate = datetime_convert('UTC','UTC', 'now - 14 days');
- }
- if(! $r) {
- $result['message'] = 'Channel not found.';
- json_return_and_die($result);
- }
-
- logger('zotfeed request: ' . $r[0]['channel_name'], LOGGER_DEBUG);
-
- $result['messages'] = zot_feed($r[0]['channel_id'],$observer['xchan_hash'],array('mindate' => $mindate));
- $result['success'] = true;
- json_return_and_die($result);
-
-
-}
diff --git a/mod/zping.php b/mod/zping.php
deleted file mode 100644
index 4cc4abb73..000000000
--- a/mod/zping.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php /** @file */
-
-require_once('include/zot.php');
-
-function zping_content(&$a) {
-
- // This is just a test utility function and may go away once we build these tools into
- // the address book and directory to do dead site discovery.
-
- // The response packet include the current URL and key so we can discover if the server
- // has been re-installed and clean up (e.g. get rid of) any old hublocs and xchans.
-
- // Remember to add '/post' to the url
-
- if(! local_channel())
- return;
-
- $url = $_REQUEST['url'];
-
- if(! $url)
- return;
-
-
- $m = zot_build_packet(App::get_channel(),'ping');
- $r = zot_zot($url,$m);
- return print_r($r,true);
-
-} \ No newline at end of file
diff --git a/util/importdoc b/util/importdoc
index b89e12e97..087f472bc 100755
--- a/util/importdoc
+++ b/util/importdoc
@@ -5,7 +5,7 @@ require_once('include/cli_startup.php');
cli_startup();
-require_once('mod/help.php');
+require_once('include/help.php');
function update_docs_dir($s) {
$f = basename($s);
diff --git a/util/typo.php b/util/typo.php
index 0f7249f5c..e9a9be5f0 100644
--- a/util/typo.php
+++ b/util/typo.php
@@ -50,12 +50,12 @@
include_once($file);
}
- echo "Directory: mod\n";
- $files = glob('mod/*.php');
- foreach($files as $file) {
- echo $file . "\n";
- include_once($file);
- }
+// echo "Directory: mod\n";
+// $files = glob('mod/*.php');
+// foreach($files as $file) {
+// echo $file . "\n";
+// include_once($file);
+// }
echo "Directory: addon\n";
$dirs = glob('addon/*');
diff --git a/view/js/main.js b/view/js/main.js
index 799ae82bc..2813b3b19 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -372,11 +372,11 @@ function NavUpdate() {
if(! updateCountsOnly) {
// start live update
- if($('#live-network').length) { src = 'network'; liveUpdate(); }
- if($('#live-channel').length) { src = 'channel'; liveUpdate(); }
- if($('#live-public').length) { src = 'public'; liveUpdate(); }
- if($('#live-display').length) { src = 'display'; liveUpdate(); }
- if($('#live-search').length) { src = 'search'; liveUpdate(); }
+ if($('#live-network').length) { src = 'network'; liveUpdate(); }
+ if($('#live-channel').length) { src = 'channel'; liveUpdate(); }
+ if($('#live-pubstream').length) { src = 'pubstream'; liveUpdate(); }
+ if($('#live-display').length) { src = 'display'; liveUpdate(); }
+ if($('#live-search').length) { src = 'search'; liveUpdate(); }
if($('#live-photos').length) {
if(liking) {
diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css
index de48ff74a..5b8729111 100644
--- a/view/theme/redbasic/css/style.css
+++ b/view/theme/redbasic/css/style.css
@@ -200,6 +200,34 @@ header #banner #logo-text {
font-size: 22px;
}
+/* contextual help */
+.help-content {
+ background: $comment_item_colour;
+ color: $font_colour;
+ position: fixed;
+ top: -50%;
+ left: 0px;
+ width: 100%;
+ max-height: 50%;
+ padding: 20px;
+ /*transition: top 300ms cubic-bezier(0.17, 0.04, 0.03, 0.94);*/
+ border-bottom: #CCC 1px solid;
+ overflow: auto;
+}
+
+.help-content-open {
+ top: 51px;
+ -moz-box-shadow: 0px 3px 3px rgba(0,0,0,0.2);
+ -webkit-box-shadow: 0px 3px 3px rgba(0,0,0,0.2);
+ box-shadow: 0px 3px 3px rgba(0,0,0,0.2);
+ /*transition: top 300ms cubic-bezier(0.17, 0.04, 0.03, 0.94);*/
+}
+
+.help-content dd {
+ margin-bottom: 1em;
+}
+/* contextual help end */
+
/* footer */
footer {
@@ -1675,9 +1703,10 @@ nav .badge.mail-update:hover {
#expand-aside,
#expand-tabs,
-#help-btn {
+#help_nav_btn_collapsed {
color: $nav_active_icon_colour;
padding: 7px 10px;
+ text-decoration: none;
}
.nav-tabs.nav-justified {
@@ -1895,31 +1924,3 @@ nav .badge.mail-update:hover {
.help-searchlist a {
font-size: 130%;
}
-
-/* contextual help */
-.help-content {
- background: rgba(255, 255, 255, 0.9);
- color: #333333;
- position: fixed;
- top: 50px;
- left: -80%;
- width: 80%;
- height: 60%;
- padding: 20px;
- transition: left 300ms cubic-bezier(0.17, 0.04, 0.03, 0.94);
- box-sizing: border-box;
- border: #CCC thin solid;
- overflow: auto;
-}
-
-.help-content-open {
- left: 0px;
- -moz-box-shadow: 3px 3px 3px #ccc;
- -webkit-box-shadow: 3px 3px 3px #ccc;
- box-shadow: 3px 3px 3px #ccc;
-}
-
-.help-content dd {
- margin-bottom: 1em;
-}
-/* contextual help end */
diff --git a/view/theme/redbasic/js/redbasic.js b/view/theme/redbasic/js/redbasic.js
index b4cde6efc..877bcd840 100644
--- a/view/theme/redbasic/js/redbasic.js
+++ b/view/theme/redbasic/js/redbasic.js
@@ -67,15 +67,3 @@ function makeFullScreen(full) {
$('main').css({'transition': ''});
}
}
-
-/* contextual help */
-$(document).mouseup(function (e) {
- var container = $("#help-content");
-
- if (!container.is(e.target) // if the target of the click isn't the container...
- && container.has(e.target).length === 0 // ... nor a descendant of the container
- && container.hasClass('help-content-open'))
- {
- container.removeClass('help-content-open');
- }
-});
diff --git a/view/theme/redbasic/schema/bluegrid.css b/view/theme/redbasic/schema/bluegrid.css
index 36e26302a..471bed5e4 100644
--- a/view/theme/redbasic/schema/bluegrid.css
+++ b/view/theme/redbasic/schema/bluegrid.css
@@ -464,4 +464,19 @@ a:hover > .icon-trash {
}
}
+.help-content {
+ color: #FFF;
+ border: none;
+}
+
+.help-content a {
+ color: #FFF;
+ font-weight: 600;
+}
+
+.help-content-open {
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
diff --git a/view/theme/redbasic/schema/dark.css b/view/theme/redbasic/schema/dark.css
index 6ed2501e1..fb18a4159 100644
--- a/view/theme/redbasic/schema/dark.css
+++ b/view/theme/redbasic/schema/dark.css
@@ -360,3 +360,14 @@ pre {
.table > tbody > tr > td {
border-color: #888;
}
+
+.help-content {
+ border-bottom: #222 thin solid;
+}
+
+.help-content-open {
+ -moz-box-shadow: 0px 3px 3px #222;
+ -webkit-box-shadow: 0px 3px 3px #222;
+ box-shadow: 0px 3px 3px #222;
+}
+
diff --git a/view/theme/redbasic/schema/simple_black_on_white.css b/view/theme/redbasic/schema/simple_black_on_white.css
index ba9771a40..e5cfb5f46 100644
--- a/view/theme/redbasic/schema/simple_black_on_white.css
+++ b/view/theme/redbasic/schema/simple_black_on_white.css
@@ -275,3 +275,13 @@ pre {
background-color: inherit;
border: none;
}
+
+.help-content {
+ border-bottom: #000 thin solid;
+}
+
+.help-content-open {
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
diff --git a/view/theme/redbasic/schema/simple_green_on_black.css b/view/theme/redbasic/schema/simple_green_on_black.css
index e6901143b..7e3f901ef 100644
--- a/view/theme/redbasic/schema/simple_green_on_black.css
+++ b/view/theme/redbasic/schema/simple_green_on_black.css
@@ -305,3 +305,13 @@ pre {
.table > tbody > tr > td {
border-color: #143D12;
}
+
+.help-content {
+ border-bottom: #143D12 thin solid;
+}
+
+.help-content-open {
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
diff --git a/view/theme/redbasic/schema/simple_white_on_black.css b/view/theme/redbasic/schema/simple_white_on_black.css
index a2d024881..d86154297 100644
--- a/view/theme/redbasic/schema/simple_white_on_black.css
+++ b/view/theme/redbasic/schema/simple_white_on_black.css
@@ -279,3 +279,13 @@ pre {
.table > tbody > tr > td {
border-color: #FFF;
}
+
+.help-content {
+ border-bottom: #FFF thin solid;
+}
+
+.help-content-open {
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
diff --git a/view/tpl/admin_site.tpl b/view/tpl/admin_site.tpl
index 54f625e0b..6b8729ee6 100755
--- a/view/tpl/admin_site.tpl
+++ b/view/tpl/admin_site.tpl
@@ -49,6 +49,7 @@
{{include file="field_input.tpl" field=$frontpage}}
{{include file="field_checkbox.tpl" field=$mirror_frontpage}}
{{include file="field_checkbox.tpl" field=$login_on_homepage}}
+ {{include file="field_checkbox.tpl" field=$enable_context_help}}
{{if $directory_server}}
{{include file="field_select.tpl" field=$directory_server}}
{{/if}}
diff --git a/view/tpl/head.tpl b/view/tpl/head.tpl
index 9fcdf1735..9502dd91c 100755
--- a/view/tpl/head.tpl
+++ b/view/tpl/head.tpl
@@ -11,6 +11,7 @@
{{$head_js}}
<link rel="shortcut icon" href="{{$icon}}" />
<link rel="search" href="{{$baseurl}}/opensearch" type="application/opensearchdescription+xml" title="{{$osearch}}" />
+<link rel="EditURI" type="application/rsd+xml" href="{{$baseurl}}/rsd.xml" />
<script>
var updateInterval = {{$update_interval}};
var localUser = {{if $local_channel}}{{$local_channel}}{{else}}false{{/if}};
diff --git a/view/tpl/nav.tpl b/view/tpl/nav.tpl
index 7f6c33c61..1c7f8f5b2 100755
--- a/view/tpl/nav.tpl
+++ b/view/tpl/nav.tpl
@@ -1,195 +1,206 @@
-<div class="container-fluid">
- <div class="navbar-header">
- <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse-1">
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- </button>
- <button id="expand-tabs" type="button" class="navbar-toggle" data-toggle="collapse" data-target="#tabs-collapse-1">
- <i class="icon-circle-arrow-down" id="expand-tabs-icon"></i>
- </button>
- <button id="expand-aside" type="button" class="navbar-toggle" data-toggle="offcanvas" data-target="#region_1">
- <i class="icon-circle-arrow-right" id="expand-aside-icon"></i>
- </button>
- {{if $nav.help}}
- <button id="help-btn" type="button" class="navbar-toggle" title="{{$nav.help.3}}" onclick="$('#help-content').toggleClass('help-content-open');">
- <i class="icon-question"></i>
- </button>
- {{/if}}
- {{if $userinfo}}
- <img class="dropdown-toggle fakelink" data-toggle="dropdown" id="avatar" src="{{$userinfo.icon}}" alt="{{$userinfo.name}}"><span class="caret" id="usermenu-caret"></span>
- {{if $localuser}}
- <ul class="dropdown-menu" role="menu" aria-labelledby="avatar">
- {{foreach $nav.usermenu as $usermenu}}
- <li role="presentation"><a href="{{$usermenu.0}}" title="{{$usermenu.3}}" role="menuitem" id="{{$usermenu.4}}">{{$usermenu.1}}</a></li>
- {{/foreach}}
- <li role="presentation" class="divider"></li>
- {{if $nav.profiles}}<li role="presentation"><a href="{{$nav.profiles.0}}" title="{{$nav.profiles.3}}" role="menuitem" id="{{$nav.profiles.4}}">{{$nav.profiles.1}}</a></li>{{/if}}
- {{if $nav.settings}}<li role="presentation"><a href="{{$nav.settings.0}}" title="{{$nav.settings.3}}" role="menuitem" id="{{$nav.settings.4}}">{{$nav.settings.1}}</a></li>{{/if}}
- {{if $nav.manage}}<li role="presentation"><a href="{{$nav.manage.0}}" title="{{$nav.manage.3}}" role="menuitem" id="{{$nav.manage.4}}">{{$nav.manage.1}}</a></li>{{/if}}
- {{if $nav.channels}}
- {{foreach $nav.channels as $chan}}
- <li role="presentation" class="nav-channel-select"><a href="manage/{{$chan.channel_id}}" title="{{$chan.channel_name}}" role="menuitem">{{$chan.channel_name}}</a></li>
- {{/foreach}}
+ <div class="container-fluid">
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse-1">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <button id="expand-tabs" type="button" class="navbar-toggle" data-toggle="collapse" data-target="#tabs-collapse-1">
+ <i class="icon-circle-arrow-down" id="expand-tabs-icon"></i>
+ </button>
+ <button id="expand-aside" type="button" class="navbar-toggle" data-toggle="offcanvas" data-target="#region_1">
+ <i class="icon-circle-arrow-right" id="expand-aside-icon"></i>
+ </button>
+ <a class="navbar-toggle" target="hubzilla-help" href="{{$nav.help.0}}" title="{{$nav.help.3}}" id="{{$nav.help.4}}_collapsed"{{if $nav.help.6}} onclick="return false;"{{/if}}>
+ {{if $nav.help.6}}<i class="icon-caret-down"></i>&nbsp;{{/if}}<i class="icon-question"></i>
+ </a>
+ {{if $userinfo}}
+ <img class="dropdown-toggle fakelink" data-toggle="dropdown" id="avatar" src="{{$userinfo.icon}}" alt="{{$userinfo.name}}"><span class="caret" id="usermenu-caret"></span>
+ {{if $localuser}}
+ <ul class="dropdown-menu" role="menu" aria-labelledby="avatar">
+ {{foreach $nav.usermenu as $usermenu}}
+ <li role="presentation"><a href="{{$usermenu.0}}" title="{{$usermenu.3}}" role="menuitem" id="{{$usermenu.4}}">{{$usermenu.1}}</a></li>
+ {{/foreach}}
+ <li role="presentation" class="divider"></li>
+ {{if $nav.profiles}}<li role="presentation"><a href="{{$nav.profiles.0}}" title="{{$nav.profiles.3}}" role="menuitem" id="{{$nav.profiles.4}}">{{$nav.profiles.1}}</a></li>{{/if}}
+ {{if $nav.settings}}<li role="presentation"><a href="{{$nav.settings.0}}" title="{{$nav.settings.3}}" role="menuitem" id="{{$nav.settings.4}}">{{$nav.settings.1}}</a></li>{{/if}}
+ {{if $nav.manage}}<li role="presentation"><a href="{{$nav.manage.0}}" title="{{$nav.manage.3}}" role="menuitem" id="{{$nav.manage.4}}">{{$nav.manage.1}}</a></li>{{/if}}
+ {{if $nav.channels}}
+ {{foreach $nav.channels as $chan}}
+ <li role="presentation" class="nav-channel-select"><a href="manage/{{$chan.channel_id}}" title="{{$chan.channel_name}}" role="menuitem">{{$chan.channel_name}}</a></li>
+ {{/foreach}}
+ {{/if}}
+ {{if $nav.admin}}
+ <li role="presentation" class="divider"></li>
+ <li role="presentation"><a href="{{$nav.admin.0}}" title="{{$nav.admin.3}}" role="menuitem" id="{{$nav.admin.4}}">{{$nav.admin.1}}</a></li>
+ {{/if}}
+ {{if $nav.logout}}
+ <li role="presentation" class="divider"></li>
+ <li role="presentation"><a href="{{$nav.logout.0}}" title="{{$nav.logout.3}}" role="menuitem" id="{{$nav.logout.4}}">{{$nav.logout.1}}</a></li>
+ {{/if}}
+ </ul>
+ {{else}}
+ {{if $nav.lock}}
+ <ul class="dropdown-menu" role="menu" aria-labelledby="avatar">
+ <li role="presentation"><a href="{{$nav.lock.0}}" title="{{$nav.lock.3}}" role="menuitem">{{$nav.lock.3}}</a></li>
+ </ul>
{{/if}}
- {{if $nav.admin}}
- <li role="presentation" class="divider"></li>
- <li role="presentation"><a href="{{$nav.admin.0}}" title="{{$nav.admin.3}}" role="menuitem" id="{{$nav.admin.4}}">{{$nav.admin.1}}</a></li>
- {{/if}}
- {{if $nav.logout}}
- <li role="presentation" class="divider"></li>
- <li role="presentation"><a href="{{$nav.logout.0}}" title="{{$nav.logout.3}}" role="menuitem" id="{{$nav.logout.4}}">{{$nav.logout.1}}</a></li>
- {{/if}}
- </ul>
- {{else}}
- {{if $nav.lock}}
- <ul class="dropdown-menu" role="menu" aria-labelledby="avatar">
- <li role="presentation"><a href="{{$nav.lock.0}}" title="{{$nav.lock.3}}" role="menuitem">{{$nav.lock.3}}</a></li>
- </ul>
{{/if}}
{{/if}}
- {{/if}}
- </div>
- <div class="collapse navbar-collapse" id="navbar-collapse-1">
- <ul class="nav navbar-nav navbar-left">
- {{if $nav.register}}<li class="{{$nav.register.2}}"><a href="{{$nav.register.0}}" title="{{$nav.register.3}}" id="{{$nav.register.4}}">{{$nav.register.1}}</a></li>{{/if}}
- {{if !$userinfo}}
+ </div>
+ <div class="collapse navbar-collapse" id="navbar-collapse-1">
+ <ul class="nav navbar-nav navbar-left">
+ {{if $nav.register}}<li class="{{$nav.register.2}}"><a href="{{$nav.register.0}}" title="{{$nav.register.3}}" id="{{$nav.register.4}}">{{$nav.register.1}}</a></li>{{/if}}
+ {{if !$userinfo}}
{{if $nav.loginmenu}}
- <li class="{{$nav.loginmenu.0.2}} hidden-xs">
- <a data-toggle="dropdown" data-target="#" href="{{$nav.loginmenu.0.0}}" title="{{$nav.loginmenu.0.3}}" id="{{$nav.loginmenu.0.4}}">{{$nav.loginmenu.0.1}} <span class="caret" id="loginmenu-caret"></span></a>
- <ul class="dropdown-menu" role="menu">
- {{foreach $nav.loginmenu as $loginmenu}}
- <li role="presentation"><a class="{{$loginmenu.2}}" href="{{$loginmenu.0}}" title="{{$loginmenu.3}}" role="menuitem" id="{{$loginmenu.4}}">{{$loginmenu.1}}</a></li>
- {{/foreach}}
- </ul>
- </li>
- {{foreach $nav.loginmenu as $loginmenu}}
- <li role="presentation"><a class="{{$loginmenu.2}} visible-xs" href="{{$loginmenu.0}}" title="{{$loginmenu.3}}" role="menuitem">{{$loginmenu.1}}</a></li>
- {{/foreach}}
+ <li class="{{$nav.loginmenu.0.2}} hidden-xs">
+ <a data-toggle="dropdown" data-target="#" href="{{$nav.loginmenu.0.0}}" title="{{$nav.loginmenu.0.3}}" id="{{$nav.loginmenu.0.4}}">{{$nav.loginmenu.0.1}} <span class="caret" id="loginmenu-caret"></span></a>
+ <ul class="dropdown-menu" role="menu">
+ {{foreach $nav.loginmenu as $loginmenu}}
+ <li role="presentation"><a class="{{$loginmenu.2}}" href="{{$loginmenu.0}}" title="{{$loginmenu.3}}" role="menuitem" id="{{$loginmenu.4}}">{{$loginmenu.1}}</a></li>
+ {{/foreach}}
+ </ul>
+ </li>
+ {{foreach $nav.loginmenu as $loginmenu}}
+ <li role="presentation"><a class="{{$loginmenu.2}} visible-xs" href="{{$loginmenu.0}}" title="{{$loginmenu.3}}" role="menuitem">{{$loginmenu.1}}</a></li>
+ {{/foreach}}
+ {{/if}}
+ {{/if}}
+
+ {{if $nav.alogout}}<li class="{{$nav}}-alogout.2"><a href="{{$nav.alogout.0}}" title="{{$nav.alogout.3}}" id="{{$nav.alogout.4}}">{{$nav.alogout.1}}</a></li>{{/if}}
+
+ {{if $nav.network}}
+ <li class="{{$sel.network}} hidden-xs">
+ <a href="{{$nav.network.0}}" title="{{$nav.network.3}}" id="{{$nav.network.4}}"><i class="icon-th"></i></a>
+ <span class="net-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-network-menu"></span>
+ <ul id="nav-network-menu" role="menu" class="dropdown-menu" rel="network">
+ {{* <li id="nav-network-see-all"><a href="{{$nav.network.all.0}}">{{$nav.network.all.1}}</a></li> *}}
+ <li id="nav-network-mark-all"><a href="#" onclick="markRead('network'); return false;">{{$nav.network.mark.1}}</a></li>
+ <li class="empty">{{$emptynotifications}}</li>
+ </ul>
+ </li>
+ <li class="{{$sel.network}} visible-xs">
+ <a href="{{$nav.network.0}}" title="{{$nav.network.3}}" ><i class="icon-th"></i></a>
+ <span class="net-update badge" rel="#nav-network-menu"></span>
+ </li>
+ {{/if}}
+
+ {{if $nav.home}}
+ <li class="{{$sel.home}} hidden-xs">
+ <a class="{{$nav.home.2}}" href="{{$nav.home.0}}" title="{{$nav.home.3}}" id="{{$nav.home.4}}"><i class="icon-home"></i></a>
+ <span class="home-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-home-menu"></span>
+ <ul id="nav-home-menu" class="dropdown-menu" rel="home">
+ {{* <li id="nav-home-see-all"><a href="{{$nav.home.all.0}}">{{$nav.home.all.1}}</a></li> *}}
+ <li id="nav-home-mark-all"><a href="#" onclick="markRead('home'); return false;">{{$nav.home.mark.1}}</a></li>
+ <li class="empty">{{$emptynotifications}}</li>
+ </ul>
+ </li>
+ <li class="{{$sel.home}} visible-xs">
+ <a class="{{$nav.home.2}}" href="{{$nav.home.0}}" title="{{$nav.home.3}}" ><i class="icon-home"></i></a>
+ <span class="home-update badge" rel="#nav-home-menu"></span>
+ </li>
+ {{/if}}
+
+
+ {{if $nav.messages}}
+ <li class="{{$sel.messages}} hidden-xs">
+ <a class="{{$nav.messages.2}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" id="{{$nav.messages.4}}"><i class="icon-envelope"></i></a>
+ <span class="mail-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-messages-menu"></span>
+ <ul id="nav-messages-menu" class="dropdown-menu" rel="messages">
+ <li id="nav-messages-see-all"><a href="{{$nav.messages.all.0}}">{{$nav.messages.all.1}}</a></li>
+ <li id="nav-messages-mark-all"><a href="#" onclick="markRead('messages'); return false;">{{$nav.messages.mark.1}}</a></li>
+ <li class="empty">{{$emptynotifications}}</li>
+ </ul>
+ </li>
+ <li class="{{$sel.messages}} visible-xs">
+ <a class="{{$nav.messages.2}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" ><i class="icon-envelope"></i></a>
+ <span class="mail-update badge" rel="#nav-messages-menu"></span>
+ </li>
+ {{/if}}
+
+ {{if $nav.all_events}}
+ <li class="{{$sel.all_events}} hidden-xs">
+ <a class="{{$nav.all_events.2}}" href="{{$nav.all_events.0}}" title="{{$nav.all_events.3}}" id='{{$nav.all_events.4}}'><i class="icon-calendar"></i></a>
+ <span class="all_events-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-all_events-menu"></span>
+ <ul id="nav-all_events-menu" class="dropdown-menu" rel="all_events">
+ <li id="nav-all_events-see-all"><a href="{{$nav.all_events.all.0}}">{{$nav.all_events.all.1}}</a></li>
+ <li id="nav-all_events-mark-all"><a href="#" onclick="markRead('all_events'); return false;">{{$nav.all_events.mark.1}}</a></li>
+ <li class="empty">{{$emptynotifications}}</li>
+ </ul>
+ </li>
+ <li class="{{$sel.all_events}} visible-xs">
+ <a class="{{$nav.all_events.2}}" href="{{$nav.all_events.0}}" title="{{$nav.all_events.3}}" ><i class="icon-calendar"></i></a>
+ <span class="all_events-update badge" rel="#nav-all_events-menu"></span>
+ </li>
+ {{/if}}
+
+ {{if $nav.intros}}
+ <li class="{{$sel.intros}} hidden-xs">
+ <a class="{{$nav.intros.2}}" href="{{$nav.intros.0}}" title="{{$nav.intros.3}}" id="{{$nav.intros.4}}"><i class="icon-user"></i></a>
+ <span class="intro-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-intros-menu"></span>
+ <ul id="nav-intros-menu" class="dropdown-menu" rel="intros">
+ <li id="nav-intros-see-all"><a href="{{$nav.intros.all.0}}">{{$nav.intros.all.1}}</a></li>
+ <li class="empty">{{$emptynotifications}}</li>
+ </ul>
+ </li>
+ <li class="{{$sel.intros}} visible-xs">
+ <a class="{{$nav.intros.2}}" href="{{$nav.intros.0}}" title="{{$nav.intros.3}}" ><i class="icon-user"></i></a>
+ <span class="intro-update badge" rel="#nav-intros-menu"></span>
+ </li>
+ {{/if}}
+
+ {{if $nav.notifications}}
+ <li class="{{$sel.notifications}} hidden-xs">
+ <a href="{{$nav.notifications.0}}" title="{{$nav.notifications.1}}" id="{{$nav.notifications.4}}"><i class="icon-exclamation"></i></a>
+ <span class="notify-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-notify-menu"></span>
+ <ul id="nav-notify-menu" class="dropdown-menu" rel="notify">
+ <li id="nav-notify-see-all"><a href="{{$nav.notifications.all.0}}">{{$nav.notifications.all.1}}</a></li>
+ <li id="nav-notify-mark-all"><a href="#" onclick="markRead('notify'); return false;">{{$nav.notifications.mark.1}}</a></li>
+ <li class="empty">{{$emptynotifications}}</li>
+ </ul>
+ </li>
+ <li class="{{$sel.notifications}} visible-xs">
+ <a href="{{$nav.notifications.0}}" title="{{$nav.notifications.1}}"><i class="icon-exclamation"></i></a>
+ <span class="notify-update badge" rel="#nav-notify-menu"></span>
+ </li>
{{/if}}
- {{/if}}
- {{if $nav.alogout}}<li class="{{$nav}}-alogout.2"><a href="{{$nav.alogout.0}}" title="{{$nav.alogout.3}}" id="{{$nav.alogout.4}}">{{$nav.alogout.1}}</a></li>{{/if}}
- {{if $nav.network}}
- <li class="{{$sel.network}} hidden-xs">
- <a href="{{$nav.network.0}}" title="{{$nav.network.3}}" id="{{$nav.network.4}}"><i class="icon-th"></i></a>
- <span class="net-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-network-menu"></span>
- <ul id="nav-network-menu" role="menu" class="dropdown-menu" rel="network">
- {{* <li id="nav-network-see-all"><a href="{{$nav.network.all.0}}">{{$nav.network.all.1}}</a></li> *}}
- <li id="nav-network-mark-all"><a href="#" onclick="markRead('network'); return false;">{{$nav.network.mark.1}}</a></li>
- <li class="empty">{{$emptynotifications}}</li>
- </ul>
- </li>
- <li class="{{$sel.network}} visible-xs">
- <a href="{{$nav.network.0}}" title="{{$nav.network.3}}" ><i class="icon-th"></i></a>
- <span class="net-update badge" rel="#nav-network-menu"></span>
- </li>
- {{/if}}
- {{if $nav.home}}
- <li class="{{$sel.home}} hidden-xs">
- <a class="{{$nav.home.2}}" href="{{$nav.home.0}}" title="{{$nav.home.3}}" id="{{$nav.home.4}}"><i class="icon-home"></i></a>
- <span class="home-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-home-menu"></span>
- <ul id="nav-home-menu" class="dropdown-menu" rel="home">
- {{* <li id="nav-home-see-all"><a href="{{$nav.home.all.0}}">{{$nav.home.all.1}}</a></li> *}}
- <li id="nav-home-mark-all"><a href="#" onclick="markRead('home'); return false;">{{$nav.home.mark.1}}</a></li>
- <li class="empty">{{$emptynotifications}}</li>
- </ul>
- </li>
- <li class="{{$sel.home}} visible-xs">
- <a class="{{$nav.home.2}}" href="{{$nav.home.0}}" title="{{$nav.home.3}}" ><i class="icon-home"></i></a>
- <span class="home-update badge" rel="#nav-home-menu"></span>
- </li>
- {{/if}}
- {{if $nav.messages}}
- <li class="{{$sel.messages}} hidden-xs">
- <a class="{{$nav.messages.2}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" id="{{$nav.messages.4}}"><i class="icon-envelope"></i></a>
- <span class="mail-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-messages-menu"></span>
- <ul id="nav-messages-menu" class="dropdown-menu" rel="messages">
- <li id="nav-messages-see-all"><a href="{{$nav.messages.all.0}}">{{$nav.messages.all.1}}</a></li>
- <li id="nav-messages-mark-all"><a href="#" onclick="markRead('messages'); return false;">{{$nav.messages.mark.1}}</a></li>
- <li class="empty">{{$emptynotifications}}</li>
- </ul>
- </li>
- <li class="{{$sel.messages}} visible-xs">
- <a class="{{$nav.messages.2}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" ><i class="icon-envelope"></i></a>
- <span class="mail-update badge" rel="#nav-messages-menu"></span>
- </li>
- {{/if}}
- {{if $nav.all_events}}
- <li class="{{$sel.all_events}} hidden-xs">
- <a class="{{$nav.all_events.2}}" href="{{$nav.all_events.0}}" title="{{$nav.all_events.3}}" id='{{$nav.all_events.4}}'><i class="icon-calendar"></i></a>
- <span class="all_events-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-all_events-menu"></span>
- <ul id="nav-all_events-menu" class="dropdown-menu" rel="all_events">
- <li id="nav-all_events-see-all"><a href="{{$nav.all_events.all.0}}">{{$nav.all_events.all.1}}</a></li>
- <li id="nav-all_events-mark-all"><a href="#" onclick="markRead('all_events'); return false;">{{$nav.all_events.mark.1}}</a></li>
- <li class="empty">{{$emptynotifications}}</li>
- </ul>
- </li>
- <li class="{{$sel.all_events}} visible-xs">
- <a class="{{$nav.all_events.2}}" href="{{$nav.all_events.0}}" title="{{$nav.all_events.3}}" ><i class="icon-calendar"></i></a>
- <span class="all_events-update badge" rel="#nav-all_events-menu"></span>
- </li>
- {{/if}}
- {{if $nav.intros}}
- <li class="{{$sel.intros}} hidden-xs">
- <a class="{{$nav.intros.2}}" href="{{$nav.intros.0}}" title="{{$nav.intros.3}}" id="{{$nav.intros.4}}"><i class="icon-user"></i></a>
- <span class="intro-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-intros-menu"></span>
- <ul id="nav-intros-menu" class="dropdown-menu" rel="intros">
- <li id="nav-intros-see-all"><a href="{{$nav.intros.all.0}}">{{$nav.intros.all.1}}</a></li>
- <li class="empty">{{$emptynotifications}}</li>
- </ul>
- </li>
- <li class="{{$sel.intros}} visible-xs">
- <a class="{{$nav.intros.2}}" href="{{$nav.intros.0}}" title="{{$nav.intros.3}}" ><i class="icon-user"></i></a>
- <span class="intro-update badge" rel="#nav-intros-menu"></span>
- </li>
- {{/if}}
- {{if $nav.notifications}}
- <li class="{{$sel.notifications}} hidden-xs">
- <a href="{{$nav.notifications.0}}" title="{{$nav.notifications.1}}" id="{{$nav.notifications.4}}"><i class="icon-exclamation"></i></a>
- <span class="notify-update badge dropdown-toggle" data-toggle="dropdown" rel="#nav-notify-menu"></span>
- <ul id="nav-notify-menu" class="dropdown-menu" rel="notify">
- <li id="nav-notify-see-all"><a href="{{$nav.notifications.all.0}}">{{$nav.notifications.all.1}}</a></li>
- <li id="nav-notify-mark-all"><a href="#" onclick="markRead('notify'); return false;">{{$nav.notifications.mark.1}}</a></li>
- <li class="empty">{{$emptynotifications}}</li>
- </ul>
- </li>
- <li class="{{$sel.notifications}} visible-xs">
- <a href="{{$nav.notifications.0}}" title="{{$nav.notifications.1}}"><i class="icon-exclamation"></i></a>
- <span class="notify-update badge" rel="#nav-notify-menu"></span>
- </li>
- {{/if}}
- </ul>
- <ul class="nav navbar-nav navbar-right">
- <li class="hidden-xs">
- <form method="get" action="search" role="search">
- <div id="nav-search-spinner"></div><input class="icon-search" id="nav-search-text" type="text" value="" placeholder="&#xf002; {{$help}}" name="search" title="{{$nav.search.3}}" onclick="this.submit();"/>
- </form>
- </li>
- <li class="visible-xs">
- <a href="/search" title="{{$nav.search.3}}"><i class="icon-search"></i></a>
- </li>
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li class="hidden-xs">
+ <form method="get" action="search" role="search">
+ <div id="nav-search-spinner"></div><input class="icon-search" id="nav-search-text" type="text" value="" placeholder="&#xf002; {{$help}}" name="search" title="{{$nav.search.3}}" onclick="this.submit();"/>
+ </form>
+ </li>
+ <li class="visible-xs">
+ <a href="/search" title="{{$nav.search.3}}"><i class="icon-search"></i></a>
+ </li>
+
{{if $powered_by}}
- <div id="powered-by">{{$powered_by}}</div>
+ <div id="powered-by">{{$powered_by}}</div>
{{/if}}
{{if $nav.directory}}
- <li class="{{$sel.directory}}">
- <a class="{{$nav.directory.2}}" href="{{$nav.directory.0}}" title="{{$nav.directory.3}}" id="{{$nav.directory.4}}"><i class="icon-sitemap"></i></a>
- </li>
+ <li class="{{$sel.directory}}">
+ <a class="{{$nav.directory.2}}" href="{{$nav.directory.0}}" title="{{$nav.directory.3}}" id="{{$nav.directory.4}}"><i class="icon-sitemap"></i></a>
+ </li>
{{/if}}
+
{{if $nav.apps}}
- <li class="{{$sel.apps}}">
- <a class="{{$nav.apps.2}}" href="{{$nav.apps.0}}" title="{{$nav.apps.3}}" id="{{$nav.apps.4}}"><i class="icon-cogs"></i></a>
- </li>
+ <li class="{{$sel.apps}}">
+ <a class="{{$nav.apps.2}}" href="{{$nav.apps.0}}" title="{{$nav.apps.3}}" id="{{$nav.apps.4}}"><i class="icon-cogs"></i></a>
+ </li>
{{/if}}
+
{{if $nav.help}}
- <li class="{{$sel.help}} hidden-xs">
- <a class="{{$nav.help.2}}" target="hubzilla-help" href="{{$nav.help.0}}" title="{{$nav.help.3}}" id="{{$nav.help.4}}" onclick="$('#help-content').toggleClass('help-content-open'); return false;"><i class="icon-question"></i></a>
- </li>
+ <li class="{{$sel.help}} hidden-xs">
+ <a class="{{$nav.help.2}}" target="hubzilla-help" href="{{$nav.help.0}}" title="{{$nav.help.3}}" id="{{$nav.help.4}}"{{if $nav.help.6}} onclick="return false;"{{/if}}>{{if $nav.help.6}}<i class="icon-caret-down"></i>&nbsp;{{/if}}<i class="icon-question"></i></a>
+ </li>
{{/if}}
- </ul>
+ </ul>
+ </div>
</div>
+ {{if $nav.help.6}}
<div id="help-content" class="help-content">
{{$nav.help.5}}
<p class="pull-right"><a href="{{$nav.help.0}}">Click here for more documentation...</a></p>
</div>
-</div>
+ {{/if}}
diff --git a/view/tpl/nav_header.tpl b/view/tpl/nav_header.tpl
new file mode 100644
index 000000000..27713b55b
--- /dev/null
+++ b/view/tpl/nav_header.tpl
@@ -0,0 +1,49 @@
+<script>
+ /* contextual help */
+ {{if $enable_context_help}}
+ $('.help-content').css('top', '-' + $('#help-content').height() + 'px')
+ $(document).mouseup(function (e)
+ {
+ e.preventDefault;
+
+ var container = $("#help-content");
+
+ if ((!container.is(e.target) // if the target of the click isn't the container...
+ && container.has(e.target).length === 0 // ... nor a descendant of the container
+ && container.hasClass('help-content-open'))
+ ||
+ (
+ ($('#help_nav_btn, #help_nav_btn_collapsed').is(e.target) || $('#help_nav_btn, #help_nav_btn_collapsed').has(e.target).length !== 0)
+ && container.hasClass('help-content-open')
+ )) {
+ container.removeClass('help-content-open');
+ $('main').removeClass('help-content-open');
+ $('main').css('top', '')
+ }
+ else if (($('#help_nav_btn, #help_nav_btn_collapsed').is(e.target) || $('#help_nav_btn, #help_nav_btn_collapsed').has(e.target).length !== 0)
+ && !container.hasClass('help-content-open')) {
+ $('#help-content').addClass('help-content-open');
+ $('main').removeClass('help-content-open');
+ var mainTop = $('#navbar-collapse-1').height();
+ if ($('#navbar-collapse-1').outerHeight(true) < $('#help-content').height()) {
+ mainTop = $('#help-content').outerHeight(true);
+ }
+
+ $('main').css('top', mainTop + 'px');
+ }
+
+ });
+ {{/if}}
+ var contextualHelpFocus = function (target, openSidePanel) {
+ if (openSidePanel) {
+ $("main").addClass('region_1-on'); // Open the side panel to highlight element
+ } else {
+ $("main").removeClass('region_1-on');
+ }
+ // Animate the page scroll to the element and then pulse the element to direct attention
+ $('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - $('#help-content').height() - 50}, 'slow');
+ for (i = 0; i < 3; i++) {
+ $(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
+ }
+ }
+</script>
diff --git a/view/tpl/rsd.tpl b/view/tpl/rsd.tpl
new file mode 100644
index 000000000..9fd02c472
--- /dev/null
+++ b/view/tpl/rsd.tpl
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">
+ <service>
+ <engineName>{{$project}}</engineName>
+ <engineLink>{{$baseurl}}</engineLink>
+ <apis>
+ <api name="Twitter" preferred="true" apiLink="{{$apipath}}" blogID="">
+ <settings>
+ <docs>http://status.net/wiki/TwitterCompatibleAPI</docs>
+ <setting name="OAuth">true</setting>
+ </settings>
+ </api>
+ </apis>
+ </service>
+</rsd> \ No newline at end of file