From 980c138f187b4f162c9f8d36b8db09ffe769ec8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaussoin=20Timoth=C3=A9e?= Date: Sun, 9 Jun 2013 00:47:22 +0200 Subject: [PATCH] - Continue the refactoring - New flat design CSS + start of the mobile version - Clean some olf CSS --- app/assets/documents/colors.txt | 5 + app/assets/js/movim.js | 6 +- app/controllers/ControllerAjax.php | 71 ++ app/controllers/ControllerBase.php | 147 +++ app/controllers/ControllerMain.php | 392 +++++++ app/widgets/.dir-locals.el | 4 + app/widgets/About/About.php | 123 +++ app/widgets/Account/Account.php | 488 +++++++++ app/widgets/Account/account.css | 15 + app/widgets/Account/account.js | 3 + app/widgets/Account/server-vcards.xml | 246 +++++ app/widgets/Admin/Admin.php | 484 +++++++++ app/widgets/Blog/Blog.php | 29 + app/widgets/Bookmark/Bookmark.php | 280 +++++ app/widgets/Bookmark/bookmark.css | 7 + app/widgets/Chat/Chat.php | 437 ++++++++ app/widgets/Chat/chat.css | 181 ++++ app/widgets/Chat/chat.js | 102 ++ app/widgets/Chat/img/arrow.png | Bin 0 -> 263 bytes app/widgets/Chat/img/cross.png | Bin 0 -> 376 bytes app/widgets/Chat/sound/notif.ogg | Bin 0 -> 20987 bytes app/widgets/ChatExt/ChatExt.php | 150 +++ app/widgets/ChatExt/chatext.css | 0 app/widgets/ChatExt/chatext.js | 31 + app/widgets/ChatPop/ChatPop.php | 45 + app/widgets/ChatPop/chatpop.css | 161 +++ app/widgets/ChatPop/chatpop.js | 46 + app/widgets/ChatPop/img/cross.png | Bin 0 -> 376 bytes app/widgets/Config/Config.php | 196 ++++ app/widgets/Config/color/arrow.gif | Bin 0 -> 66 bytes app/widgets/Config/color/cross.gif | Bin 0 -> 83 bytes app/widgets/Config/color/demo.html | 12 + app/widgets/Config/color/hs.png | Bin 0 -> 2684 bytes app/widgets/Config/color/hv.png | Bin 0 -> 2865 bytes app/widgets/Config/color/jscolor.js | 953 ++++++++++++++++++ app/widgets/Config/config.css | 0 app/widgets/ConfigData/ConfigData.php | 104 ++ app/widgets/ConfigData/configdata.css | 0 app/widgets/ContactCard/ContactCard.php | 143 +++ app/widgets/ContactCard/contactcard.css | 8 + app/widgets/ContactInfo/ContactInfo.php | 214 ++++ app/widgets/ContactManage/ContactManage.php | 83 ++ .../ContactPubsubSubscription.php | 75 ++ app/widgets/ContactSummary/ContactSummary.php | 104 ++ app/widgets/ContactSummary/contactsummary.css | 28 + app/widgets/Explore/Explore.php | 160 +++ app/widgets/Explore/explore.css | 4 + app/widgets/Feed/Feed.php | 213 ++++ app/widgets/Feed/feed.css | 1 + app/widgets/Feed/feed.js | 21 + app/widgets/Help/Help.php | 74 ++ app/widgets/Help/help.css | 0 app/widgets/Log/Log.php | 49 + app/widgets/Log/log.css | 29 + app/widgets/Login/Login.php | 335 ++++++ app/widgets/Login/img/beaker.png | Bin 0 -> 316 bytes app/widgets/Login/img/envelope.png | Bin 0 -> 336 bytes app/widgets/Login/img/facebook.png | Bin 0 -> 259 bytes app/widgets/Login/img/jabber.png | Bin 0 -> 616 bytes app/widgets/Login/img/logo.png | Bin 0 -> 7190 bytes app/widgets/Login/img/logo.svg | 512 ++++++++++ app/widgets/Login/img/logo2.svg | 238 +++++ app/widgets/Login/login.css | 155 +++ app/widgets/Login/login.js | 12 + app/widgets/Logout/Logout.php | 125 +++ app/widgets/Logout/img/away.png | Bin 0 -> 436 bytes app/widgets/Logout/img/dnd.png | Bin 0 -> 398 bytes .../widgets/Logout/img}/door_open.png | Bin app/widgets/Logout/img/online.png | Bin 0 -> 391 bytes app/widgets/Logout/img/xa.png | Bin 0 -> 432 bytes app/widgets/Logout/logout.css | 60 ++ app/widgets/Logout/logout.js | 9 + app/widgets/Media/Media.php | 158 +++ app/widgets/Media/img/paper.png | Bin 0 -> 8131 bytes app/widgets/Media/media.css | 115 +++ app/widgets/Media/media.js | 181 ++++ app/widgets/MediaUpload/MediaUpload.php | 86 ++ app/widgets/MediaUpload/mediaupload.css | 28 + app/widgets/Node/Node.php | 240 +++++ .../NodeAffiliations/NodeAffiliations.php | 103 ++ app/widgets/NodeConfig/NodeConfig.php | 119 +++ app/widgets/Notification/Notification.php | 51 + app/widgets/Notification/img/error.png | Bin 0 -> 246 bytes app/widgets/Notification/img/info.png | Bin 0 -> 237 bytes app/widgets/Notification/img/success.png | Bin 0 -> 319 bytes app/widgets/Notification/img/warning.png | Bin 0 -> 138 bytes app/widgets/Notification/notification.css | 71 ++ app/widgets/Notification/notification.js | 21 + app/widgets/Notifs/Notifs.php | 290 ++++++ app/widgets/Notifs/notifs.css | 134 +++ app/widgets/Notifs/notifs.js | 64 ++ app/widgets/Poller/Poller.php | 35 + app/widgets/Poller/poller.js | 70 ++ app/widgets/Profile/Profile.php | 144 +++ app/widgets/Profile/profile.css | 47 + app/widgets/Profile/profile.js | 13 + app/widgets/ProfileData/ProfileData.php | 123 +++ app/widgets/ProfileData/profiledata.js | 61 ++ .../PubsubSubscriptionConfig.php | 83 ++ app/widgets/Roster/Roster.php | 402 ++++++++ app/widgets/Roster/geany_run_script.sh | 16 + app/widgets/Roster/img/away.png | Bin 0 -> 306 bytes app/widgets/Roster/img/background.png | Bin 0 -> 16871 bytes app/widgets/Roster/img/bubbles.png | Bin 0 -> 262 bytes app/widgets/Roster/img/dnd.png | Bin 0 -> 308 bytes app/widgets/Roster/img/earth.png | Bin 0 -> 390 bytes app/widgets/Roster/img/mobile.png | Bin 0 -> 128 bytes app/widgets/Roster/img/music.png | Bin 0 -> 204 bytes app/widgets/Roster/img/offline.png | Bin 0 -> 297 bytes app/widgets/Roster/img/online.png | Bin 0 -> 317 bytes app/widgets/Roster/img/robot.png | Bin 0 -> 364 bytes app/widgets/Roster/img/server_error.png | Bin 0 -> 423 bytes app/widgets/Roster/img/xa.png | Bin 0 -> 311 bytes app/widgets/Roster/roster.css | 186 ++++ app/widgets/Roster/roster.js | 312 ++++++ app/widgets/ServerNodes/ServerNodes.php | 199 ++++ app/widgets/Syndication/Syndication.php | 77 ++ app/widgets/Tabs/Tabs.php | 37 + app/widgets/Tabs/tabs.css | 29 + app/widgets/Tabs/tabs.js | 43 + app/widgets/Vcard/Vcard.php | 374 +++++++ app/widgets/Vcard/vcard.css | 26 + app/widgets/Vcard/vcard.js | 110 ++ app/widgets/Wall/Wall.php | 142 +++ app/widgets/Wall/i18n/fr_fr.po | 22 + app/widgets/Wall/i18n/messages.pot | 22 + app/widgets/Wall/wall.css | 9 + app/widgets/Wall/wall.js | 5 + loader.php | 6 +- system/UtilsPicture.php | 2 +- system/widget/WidgetBase.php | 227 +++++ system/widget/WidgetCommon.php | 582 +++++++++++ system/widget/WidgetWrapper.php | 228 +++++ themes/movim/account.tpl | 9 +- themes/movim/blog.tpl | 3 +- themes/movim/conf.tpl | 2 +- themes/movim/css/forms.css | 190 +++- themes/movim/css/mobile.css | 18 +- themes/movim/css/posts.css | 108 +- themes/movim/css/style2.css | 112 +- themes/movim/css/submitform.css | 25 +- themes/movim/explore.tpl | 3 +- themes/movim/friend.tpl | 2 +- themes/movim/help.tpl | 2 +- themes/movim/img/icons/address.png | Bin 271 -> 0 bytes themes/movim/img/icons/back_icon.png | Bin 325 -> 0 bytes themes/movim/img/icons/birth.png | Bin 228 -> 0 bytes themes/movim/img/icons/button/arrow-left.png | Bin 127 -> 121 bytes themes/movim/img/icons/button/arrow-right.png | Bin 127 -> 119 bytes themes/movim/img/icons/button/bubbles.png | Bin 0 -> 262 bytes themes/movim/img/icons/button/chat.png | Bin 231 -> 0 bytes themes/movim/img/icons/button/checkmark.png | Bin 157 -> 145 bytes themes/movim/img/icons/button/close.png | Bin 161 -> 148 bytes themes/movim/img/icons/button/comment.png | Bin 179 -> 0 bytes themes/movim/img/icons/button/envelope.png | Bin 219 -> 195 bytes themes/movim/img/icons/button/eye.png | Bin 260 -> 213 bytes themes/movim/img/icons/button/feed.png | Bin 326 -> 265 bytes themes/movim/img/icons/button/home.png | Bin 0 -> 166 bytes themes/movim/img/icons/button/image.png | Bin 221 -> 201 bytes themes/movim/img/icons/button/images.png | Bin 0 -> 203 bytes themes/movim/img/icons/button/link.png | Bin 281 -> 235 bytes themes/movim/img/icons/button/location.png | Bin 252 -> 208 bytes themes/movim/img/icons/button/loop.png | Bin 285 -> 234 bytes themes/movim/img/icons/button/map.png | Bin 0 -> 178 bytes themes/movim/img/icons/button/minus.png | Bin 105 -> 100 bytes themes/movim/img/icons/button/music.png | Bin 0 -> 226 bytes themes/movim/img/icons/button/pencil.png | Bin 260 -> 214 bytes themes/movim/img/icons/button/plus.png | Bin 148 -> 135 bytes themes/movim/img/icons/button/quill.png | Bin 270 -> 217 bytes themes/movim/img/icons/button/remove.png | Bin 216 -> 180 bytes themes/movim/img/icons/button/search.png | Bin 0 -> 216 bytes themes/movim/img/icons/button/share.png | Bin 0 -> 185 bytes themes/movim/img/icons/button/support.png | Bin 248 -> 217 bytes themes/movim/img/icons/button/tag.png | Bin 192 -> 174 bytes themes/movim/img/icons/button/upload.png | Bin 183 -> 167 bytes themes/movim/img/icons/button/user.png | Bin 0 -> 185 bytes themes/movim/img/icons/button/users.png | Bin 0 -> 218 bytes themes/movim/img/icons/chat_icon.png | Bin 296 -> 0 bytes themes/movim/img/icons/comments_add.png | Bin 217 -> 0 bytes themes/movim/img/icons/comments_icon.png | Bin 214 -> 0 bytes themes/movim/img/icons/comments_show.png | Bin 210 -> 0 bytes themes/movim/img/icons/female.png | Bin 369 -> 0 bytes themes/movim/img/icons/follow_icon.png | Bin 458 -> 0 bytes themes/movim/img/icons/hearth.png | Bin 307 -> 0 bytes themes/movim/img/icons/loading.gif | Bin 847 -> 0 bytes themes/movim/img/icons/male.png | Bin 349 -> 0 bytes themes/movim/img/icons/mobile.png | Bin 227 -> 0 bytes themes/movim/img/icons/next_icon.png | Bin 318 -> 0 bytes themes/movim/img/icons/no_icon.png | Bin 251 -> 0 bytes themes/movim/img/icons/rm_icon.png | Bin 192 -> 0 bytes themes/movim/img/icons/submit_icon.png | Bin 322 -> 0 bytes themes/movim/img/icons/yes_icon.png | Bin 372 -> 0 bytes themes/movim/main.tpl | 6 +- themes/movim/media.tpl | 2 +- themes/movim/node.tpl | 3 +- themes/movim/page.tpl | 6 +- themes/movim/profile.tpl | 2 +- themes/movim/server.tpl | 2 +- 198 files changed, 12921 insertions(+), 237 deletions(-) create mode 100644 app/assets/documents/colors.txt create mode 100644 app/controllers/ControllerAjax.php create mode 100644 app/controllers/ControllerBase.php create mode 100644 app/controllers/ControllerMain.php create mode 100644 app/widgets/.dir-locals.el create mode 100644 app/widgets/About/About.php create mode 100644 app/widgets/Account/Account.php create mode 100644 app/widgets/Account/account.css create mode 100644 app/widgets/Account/account.js create mode 100644 app/widgets/Account/server-vcards.xml create mode 100644 app/widgets/Admin/Admin.php create mode 100644 app/widgets/Blog/Blog.php create mode 100644 app/widgets/Bookmark/Bookmark.php create mode 100644 app/widgets/Bookmark/bookmark.css create mode 100644 app/widgets/Chat/Chat.php create mode 100644 app/widgets/Chat/chat.css create mode 100644 app/widgets/Chat/chat.js create mode 100644 app/widgets/Chat/img/arrow.png create mode 100644 app/widgets/Chat/img/cross.png create mode 100644 app/widgets/Chat/sound/notif.ogg create mode 100644 app/widgets/ChatExt/ChatExt.php create mode 100644 app/widgets/ChatExt/chatext.css create mode 100644 app/widgets/ChatExt/chatext.js create mode 100644 app/widgets/ChatPop/ChatPop.php create mode 100644 app/widgets/ChatPop/chatpop.css create mode 100644 app/widgets/ChatPop/chatpop.js create mode 100644 app/widgets/ChatPop/img/cross.png create mode 100644 app/widgets/Config/Config.php create mode 100644 app/widgets/Config/color/arrow.gif create mode 100644 app/widgets/Config/color/cross.gif create mode 100644 app/widgets/Config/color/demo.html create mode 100644 app/widgets/Config/color/hs.png create mode 100644 app/widgets/Config/color/hv.png create mode 100644 app/widgets/Config/color/jscolor.js create mode 100644 app/widgets/Config/config.css create mode 100644 app/widgets/ConfigData/ConfigData.php create mode 100644 app/widgets/ConfigData/configdata.css create mode 100644 app/widgets/ContactCard/ContactCard.php create mode 100644 app/widgets/ContactCard/contactcard.css create mode 100644 app/widgets/ContactInfo/ContactInfo.php create mode 100644 app/widgets/ContactManage/ContactManage.php create mode 100644 app/widgets/ContactPubsubSubscription/ContactPubsubSubscription.php create mode 100644 app/widgets/ContactSummary/ContactSummary.php create mode 100644 app/widgets/ContactSummary/contactsummary.css create mode 100644 app/widgets/Explore/Explore.php create mode 100644 app/widgets/Explore/explore.css create mode 100644 app/widgets/Feed/Feed.php create mode 100644 app/widgets/Feed/feed.css create mode 100644 app/widgets/Feed/feed.js create mode 100644 app/widgets/Help/Help.php create mode 100644 app/widgets/Help/help.css create mode 100644 app/widgets/Log/Log.php create mode 100644 app/widgets/Log/log.css create mode 100644 app/widgets/Login/Login.php create mode 100644 app/widgets/Login/img/beaker.png create mode 100644 app/widgets/Login/img/envelope.png create mode 100644 app/widgets/Login/img/facebook.png create mode 100644 app/widgets/Login/img/jabber.png create mode 100644 app/widgets/Login/img/logo.png create mode 100644 app/widgets/Login/img/logo.svg create mode 100644 app/widgets/Login/img/logo2.svg create mode 100644 app/widgets/Login/login.css create mode 100644 app/widgets/Login/login.js create mode 100644 app/widgets/Logout/Logout.php create mode 100644 app/widgets/Logout/img/away.png create mode 100644 app/widgets/Logout/img/dnd.png rename {themes/movim/img/icons => app/widgets/Logout/img}/door_open.png (100%) create mode 100644 app/widgets/Logout/img/online.png create mode 100644 app/widgets/Logout/img/xa.png create mode 100644 app/widgets/Logout/logout.css create mode 100644 app/widgets/Logout/logout.js create mode 100644 app/widgets/Media/Media.php create mode 100644 app/widgets/Media/img/paper.png create mode 100644 app/widgets/Media/media.css create mode 100644 app/widgets/Media/media.js create mode 100644 app/widgets/MediaUpload/MediaUpload.php create mode 100644 app/widgets/MediaUpload/mediaupload.css create mode 100644 app/widgets/Node/Node.php create mode 100644 app/widgets/NodeAffiliations/NodeAffiliations.php create mode 100644 app/widgets/NodeConfig/NodeConfig.php create mode 100644 app/widgets/Notification/Notification.php create mode 100644 app/widgets/Notification/img/error.png create mode 100644 app/widgets/Notification/img/info.png create mode 100644 app/widgets/Notification/img/success.png create mode 100644 app/widgets/Notification/img/warning.png create mode 100644 app/widgets/Notification/notification.css create mode 100644 app/widgets/Notification/notification.js create mode 100644 app/widgets/Notifs/Notifs.php create mode 100644 app/widgets/Notifs/notifs.css create mode 100644 app/widgets/Notifs/notifs.js create mode 100644 app/widgets/Poller/Poller.php create mode 100644 app/widgets/Poller/poller.js create mode 100644 app/widgets/Profile/Profile.php create mode 100644 app/widgets/Profile/profile.css create mode 100644 app/widgets/Profile/profile.js create mode 100644 app/widgets/ProfileData/ProfileData.php create mode 100644 app/widgets/ProfileData/profiledata.js create mode 100644 app/widgets/PubsubSubscriptionConfig/PubsubSubscriptionConfig.php create mode 100644 app/widgets/Roster/Roster.php create mode 100755 app/widgets/Roster/geany_run_script.sh create mode 100644 app/widgets/Roster/img/away.png create mode 100644 app/widgets/Roster/img/background.png create mode 100644 app/widgets/Roster/img/bubbles.png create mode 100644 app/widgets/Roster/img/dnd.png create mode 100644 app/widgets/Roster/img/earth.png create mode 100644 app/widgets/Roster/img/mobile.png create mode 100644 app/widgets/Roster/img/music.png create mode 100644 app/widgets/Roster/img/offline.png create mode 100644 app/widgets/Roster/img/online.png create mode 100644 app/widgets/Roster/img/robot.png create mode 100644 app/widgets/Roster/img/server_error.png create mode 100644 app/widgets/Roster/img/xa.png create mode 100644 app/widgets/Roster/roster.css create mode 100644 app/widgets/Roster/roster.js create mode 100644 app/widgets/ServerNodes/ServerNodes.php create mode 100644 app/widgets/Syndication/Syndication.php create mode 100644 app/widgets/Tabs/Tabs.php create mode 100644 app/widgets/Tabs/tabs.css create mode 100644 app/widgets/Tabs/tabs.js create mode 100644 app/widgets/Vcard/Vcard.php create mode 100644 app/widgets/Vcard/vcard.css create mode 100644 app/widgets/Vcard/vcard.js create mode 100644 app/widgets/Wall/Wall.php create mode 100644 app/widgets/Wall/i18n/fr_fr.po create mode 100644 app/widgets/Wall/i18n/messages.pot create mode 100644 app/widgets/Wall/wall.css create mode 100644 app/widgets/Wall/wall.js create mode 100644 system/widget/WidgetBase.php create mode 100644 system/widget/WidgetCommon.php create mode 100644 system/widget/WidgetWrapper.php delete mode 100644 themes/movim/img/icons/address.png delete mode 100644 themes/movim/img/icons/back_icon.png delete mode 100644 themes/movim/img/icons/birth.png create mode 100644 themes/movim/img/icons/button/bubbles.png delete mode 100644 themes/movim/img/icons/button/chat.png delete mode 100644 themes/movim/img/icons/button/comment.png create mode 100644 themes/movim/img/icons/button/home.png create mode 100644 themes/movim/img/icons/button/images.png create mode 100644 themes/movim/img/icons/button/map.png create mode 100644 themes/movim/img/icons/button/music.png create mode 100644 themes/movim/img/icons/button/search.png create mode 100644 themes/movim/img/icons/button/share.png create mode 100644 themes/movim/img/icons/button/user.png create mode 100644 themes/movim/img/icons/button/users.png delete mode 100644 themes/movim/img/icons/chat_icon.png delete mode 100644 themes/movim/img/icons/comments_add.png delete mode 100644 themes/movim/img/icons/comments_icon.png delete mode 100644 themes/movim/img/icons/comments_show.png delete mode 100644 themes/movim/img/icons/female.png delete mode 100644 themes/movim/img/icons/follow_icon.png delete mode 100644 themes/movim/img/icons/hearth.png delete mode 100644 themes/movim/img/icons/loading.gif delete mode 100644 themes/movim/img/icons/male.png delete mode 100644 themes/movim/img/icons/mobile.png delete mode 100644 themes/movim/img/icons/next_icon.png delete mode 100644 themes/movim/img/icons/no_icon.png delete mode 100644 themes/movim/img/icons/rm_icon.png delete mode 100644 themes/movim/img/icons/submit_icon.png delete mode 100644 themes/movim/img/icons/yes_icon.png diff --git a/app/assets/documents/colors.txt b/app/assets/documents/colors.txt new file mode 100644 index 000000000..caf5caeb6 --- /dev/null +++ b/app/assets/documents/colors.txt @@ -0,0 +1,5 @@ +red : #D92727 +orange : #FC8F12 +yellow : #FFE433 +green : #6FCC43 +blue : #0DB8B5 diff --git a/app/assets/js/movim.js b/app/assets/js/movim.js index e450554a3..031037dfb 100644 --- a/app/assets/js/movim.js +++ b/app/assets/js/movim.js @@ -148,11 +148,11 @@ function getFeedMessage() { } function frameHeight(n, text) { - if(n.className == 'button tiny icon alone add merged') { - n.className = 'button tiny icon alone rm merged'; + if(n.className == 'button icon color alone add merged') { + n.className = 'button icon color alone rm merged'; text.style.minHeight = '20em'; } else { - n.className = 'button tiny icon alone add merged'; + n.className = 'button icon color alone add merged'; text.style.minHeight = '1.5em'; } } diff --git a/app/controllers/ControllerAjax.php b/app/controllers/ControllerAjax.php new file mode 100644 index 000000000..09d18cae1 --- /dev/null +++ b/app/controllers/ControllerAjax.php @@ -0,0 +1,71 @@ + + * + * @version 1.0 + * @date 8 November 2010 + * + * Copyright (C)2010 PROPRIETOR + * + * OTHER T&C IF ANY + */ + +class ControllerAjax extends ControllerBase +{ + protected $funclist = array(); + protected static $instance; + + public function __construct() + { + parent::__construct(); + } + + public static function getInstance() + { + if(!is_object(self::$instance)) { + self::$instance = new ControllerAjax(); + } + return self::$instance; + } + + /** + * Generates the javascript part of the ajax. + */ + public function genJs() + { + if(empty($this->funclist)) { + return ''; + } + + $buffer = '\n"; + } + + /** + * Defines a new function. + */ + public function defun($widget, $funcname, array $params) + { + $this->funclist[] = array( + 'object' => $widget, + 'funcname' => $funcname, + 'params' => $params, + ); + } +} + +?> diff --git a/app/controllers/ControllerBase.php b/app/controllers/ControllerBase.php new file mode 100644 index 000000000..72022d18f --- /dev/null +++ b/app/controllers/ControllerBase.php @@ -0,0 +1,147 @@ + + * + * @version 1.0 + * @date 13 October 2010 + * + * Copyright (C)2010 Movim Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +class ControllerBase +{ + protected $default_handler = 'index'; + protected $token; + + public function __construct($token = 'q') + { + $this->load_language(); + $this->token = $token; + } + + public function handle() + { + + $r = new Route(); + // Note that the request is always specified by 'q'. + $request; + if($request = $this->fetch_get('q')) { + $this->run_req($request); + } else { + $this->run_req($this->default_handler); + } + } + + /** + * Loads up the language, either from the User or default. + */ + function load_language() { + $user = new user(); + if($user->isLogged()) { + try{ + $lang = $user->getConfig('language'); + load_language($lang); + } + catch(MovimException $e) { + // Load default language. + load_language(Conf::getServerConfElement('defLang')); + } + } + else if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + load_language_auto(); + } + else { + load_language(Conf::getServerConfElement('defLang')); + } + } + + /** + * Attempts to call back the given function. + */ + protected function run_req($request) + { + if(is_callable(array($this, $request))) { + call_user_func(array($this, $request)); + } else { + $this->error404(); + } + } + + /** + * Returns the value of a $_GET variable. Mainly used to avoid getting + * notices from PHP when attempting to fetch an empty variable. + * @param name is the desired variable's name. + * @return the value of the requested variable, or FALSE. + */ + protected function fetch_get($name) + { + if(isset($_GET[$name])) { + return htmlentities($_GET[$name]); + } else { + return false; + } + } + + /** + * Returns the value of a $_POST variable. Mainly used to avoid getting + * notices from PHP when attempting to fetch an empty variable. + * @param name is the desired variable's name. + * @return the value of the requested variable, or FALSE. + */ + protected function fetch_post($name) + { + if(isset($_POST[$name])) { + return htmlentities($_POST[$name]); + } else { + return false; + } + } + + /** + * Return a basic auth page for the administration area + */ + protected function authenticate(){ + header('WWW-Authenticate: Basic realm="Enter admin username/password"'); + header('HTTP/1.0 401 Unauthorized'); + echo 'Why are you hitting cancel?'; + exit; + } + + /** + * Makes an error 404 page. + */ + protected function error404() + { + //echo 'Error 404 - Page not found'; + $page = new TplPageBuilder(); + + $page->setTitle(t('%s - 404', APP_TITLE)); + $page->menuAddLink(t('Home'), 'main', true); + + $content = new TplPageBuilder(); + $page->setContent($content->build('404.tpl')); + echo $page->build('page.tpl'); + } +} + +?> diff --git a/app/controllers/ControllerMain.php b/app/controllers/ControllerMain.php new file mode 100644 index 000000000..e1c9199ac --- /dev/null +++ b/app/controllers/ControllerMain.php @@ -0,0 +1,392 @@ + + * + * @version 1.0 + * @date 21 October 2010 + * + * Copyright (C)2010 MOVIM Project + * + * See COPYING for licensing deatils. + */ + +class ControllerMain extends ControllerBase +{ + protected $default_handler = 'main'; + private $page; + + function __construct() + { + parent::__construct(); + + $this->page = new TplPageBuilder(); + $this->page->addScript('movim.js'); + $this->page->addScript('hash.js'); + $this->page->addScript('movimrpc.js'); + } + + function main() + { + $user = new User(); + + if(!$user->isLogged()) { + $this->login(); + } else { + $this->page->setTitle(t('%s - Welcome to Movim', APP_TITLE)); + $this->page->menuAddLink(t('Home'), 'main', true); + $this->page->menuAddLink(t('Explore'), 'explore'); + $this->page->menuAddLink(t('Profile'), 'profile'); + $this->page->menuAddLink(t('Media'), 'media'); + $this->page->menuAddLink(t('Configuration'), 'conf'); + $this->page->menuAddLink(t('Help'), 'help'); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + + $content = new TplPageBuilder($user); + + $this->page->setContent($content->build('main.tpl')); + echo $this->page->build('page.tpl'); + } + } + + function friend() + { + $user = new User(); + + $cd = new \modl\ContactDAO(); + $contact = $cd->get($_GET['f']); + + if(isset($contact)) + $name = $contact->getTrueName(); + else + $name = $_GET['f']; + + if(!$user->isLogged()) { + $this->login(); + } else { + if(isset($_GET['f']) && $_GET['f'] != "" ) { + $this->page->setTitle(APP_TITLE.' - '.$name); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Explore'), 'explore'); + $this->page->menuAddLink(t('Profile'), 'profile'); + $this->page->menuAddLink(t('Media'), 'media'); + $this->page->menuAddLink(t('Configuration'), 'conf'); + $this->page->menuAddLink(t('Help'), 'help'); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + + $content = new TplPageBuilder($user); + + $this->page->setContent($content->build('friend.tpl')); + echo $this->page->build('page.tpl'); + } + else + $this->main(); + } + } + + function server() + { + $user = new User(); + + if(!$user->isLogged()) { + $this->login(); + } else { + if(isset($_GET['s']) && $_GET['s'] != "" ) { + $this->page->setTitle(APP_TITLE.' - Server'); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Explore'), 'explore'); + $this->page->menuAddLink(t('Profile'), 'profile'); + $this->page->menuAddLink(t('Media'), 'media'); + $this->page->menuAddLink(t('Configuration'), 'conf'); + $this->page->menuAddLink(t('Help'), 'help'); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + + $content = new TplPageBuilder($user); + + $this->page->setContent($content->build('server.tpl')); + echo $this->page->build('page.tpl'); + } + else + $this->main(); + } + } + + function node() + { + $user = new User(); + + if(!$user->isLogged()) { + $this->login(); + } else { + if(isset($_GET['n']) && $_GET['n'] != "" ) { + $this->page->setTitle(APP_TITLE.' - Node'); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Explore'), 'explore'); + $this->page->menuAddLink(t('Profile'), 'profile'); + $this->page->menuAddLink(t('Media'), 'media'); + $this->page->menuAddLink(t('Configuration'), 'conf'); + $this->page->menuAddLink(t('Help'), 'help'); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + + $content = new TplPageBuilder($user); + + $this->page->setContent($content->build('node.tpl')); + echo $this->page->build('page.tpl'); + } + else + $this->main(); + } + } + + function media() + { + $user = new User(); + + if(!$user->isLogged()) { + $this->login(); + } else { + $this->page->setTitle(APP_TITLE.' - Node'); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Explore'), 'explore'); + $this->page->menuAddLink(t('Profile'), 'profile'); + $this->page->menuAddLink(t('Media'), 'media', true); + $this->page->menuAddLink(t('Configuration'), 'conf'); + $this->page->menuAddLink(t('Help'), 'help'); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + + $content = new TplPageBuilder($user); + + $this->page->setContent($content->build('media.tpl')); + echo $this->page->build('page.tpl'); + } + } + + function conf() + { + $user = new User(); + + if(!$user->isLogged()) { + $this->login(); + } else { + $this->page->setTitle(t('%s - Configuration', APP_TITLE)); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Explore'), 'explore'); + $this->page->menuAddLink(t('Profile'), 'profile'); + $this->page->menuAddLink(t('Media'), 'media'); + $this->page->menuAddLink(t('Configuration'), 'conf', true); + $this->page->menuAddLink(t('Help'), 'help'); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + + $content = new TplPageBuilder($user); + + $this->page->setContent($content->build('conf.tpl')); + echo $this->page->build('page.tpl'); + } + } + + function profile() + { + $user = new User(); + + if(!$user->isLogged()) { + $this->login(); + } else { + $this->page->setTitle(t('%s - Profile', APP_TITLE)); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Explore'), 'explore'); + $this->page->menuAddLink(t('Profile'), 'profile', true); + $this->page->menuAddLink(t('Media'), 'media'); + $this->page->menuAddLink(t('Configuration'), 'conf'); + $this->page->menuAddLink(t('Help'), 'help'); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + + $content = new TplPageBuilder($user); + + $this->page->setContent($content->build('profile.tpl')); + echo $this->page->build('page.tpl'); + } + } + + function account() + { + $this->page->setTitle(t('%s - Account', APP_TITLE)); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Account Creation'), 'account', true); + $content = new TplPageBuilder(); + + $this->page->setContent($content->build('account.tpl')); + echo $this->page->build('page.tpl'); + } + + function blog() + { + $this->page->setTitle(t('%s - Account', APP_TITLE)); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Blog'), 'blog', true); + $content = new TplPageBuilder(); + + $this->page->setContent($content->build('blog.tpl')); + echo $this->page->build('page.tpl'); + } + + function about() + { + $this->page->setTitle(t('%s - About', APP_TITLE)); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('About'), 'about', true); + $content = new TplPageBuilder(); + + $this->page->setContent($content->build('about.tpl')); + echo $this->page->build('page.tpl'); + } + + function chatpop() + { + $user = new User(); + + if(!$user->isLogged()) { + $this->login(); + } else { + echo $this->page->build('chatpop.tpl'); + } + } + + function post() + { + $user = new User(); + + if(!$user->isLogged()) { + $this->login(); + } else { + $this->page->setTitle(t('%s - Post View', APP_TITLE)); + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Explore'), 'explore'); + $this->page->menuAddLink(t('Profile'), 'profile'); + $this->page->menuAddLink(t('Configuration'), 'conf'); + $this->page->menuAddLink(t('Help'), 'help'); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + + $content = new TplPageBuilder($user); + + $this->page->setContent($content->build('post.tpl')); + echo $this->page->build('page.tpl'); + } + } + + /** + * Show login interface + */ + function login() + { + $this->page->setTitle(t('%s - Login to Movim', APP_TITLE)); + $this->page->menuAddLink(t('Home'), 'main', true); + $this->page->menuAddLink(t('About'), 'about'); + + $content = new TplPageBuilder($user); + $this->page->setContent($content->build('login.tpl')); + echo $this->page->build('page.tpl'); + } + + /** + * Create the Atom feed of a user + */ + function feed() + { + $content = new TplPageBuilder(); + echo $content->build('feed.tpl'); + } + + /** + * Explore the XMPP network + */ + function explore() + { + $user = new User(); + + $this->page->setTitle(t('%s - Explore', APP_TITLE)); + + if(!$user->isLogged()) { + $this->login(); + } else { + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Explore'), 'explore', true); + $this->page->menuAddLink(t('Profile'), 'profile'); + $this->page->menuAddLink(t('Media'), 'media'); + $this->page->menuAddLink(t('Configuration'), 'conf'); + $this->page->menuAddLink(t('Help'), 'help'); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + } + + $content = new TplPageBuilder($user); + $this->page->setContent($content->build('explore.tpl')); + echo $this->page->build('page.tpl'); + } + + + /* + * Show help page + */ + function help() + { + $user = new User(); + + + $this->page->setTitle(t('%s - Help Page', APP_TITLE)); + + if(!$user->isLogged()) { + $this->login(); + } else { + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Explore'), 'explore'); + $this->page->menuAddLink(t('Profile'), 'profile'); + $this->page->menuAddLink(t('Media'), 'media'); + $this->page->menuAddLink(t('Configuration'), 'conf'); + $this->page->menuAddLink(t('Help'), 'help', true); + $this->page->menuAddLink(t('Logout'), 'disconnect'); + } + + $content = new TplPageBuilder($user); + $this->page->setContent($content->build('help.tpl')); + echo $this->page->build('page.tpl'); + + } + + /* + * Show admin page + */ + function admin() + { + error_reporting(0); + + if(!isset($_SERVER['PHP_AUTH_USER'])) { + $this->authenticate(); + } else { + $conf = Conf::getServerConf(); + + if($_SERVER['PHP_AUTH_USER'] == (string)$conf['user'] && sha1($_SERVER['PHP_AUTH_PW']) == (string)$conf['pass']){ + $this->page->setTitle(t('%s - Administration Panel', APP_TITLE)); + + $this->page->menuAddLink(t('Home'), 'main'); + $this->page->menuAddLink(t('Administration'), 'admin', true); + + $content = new TplPageBuilder(); + $this->page->setContent($content->build('admin.tpl')); + echo $this->page->build('page.tpl'); + } else { + $this->authenticate(); + } + } + + } + + function disconnect() + { + $user = new User(); + $user->desauth(); + $this->login(); + } +} diff --git a/app/widgets/.dir-locals.el b/app/widgets/.dir-locals.el new file mode 100644 index 000000000..b6f02a60e --- /dev/null +++ b/app/widgets/.dir-locals.el @@ -0,0 +1,4 @@ +((nil . ((indent-tabs-mode . nil) + (tab-width . 4) + (fill-column . 80))) + (c-mode . ((c-file-style . "stroustrup")))) diff --git a/app/widgets/About/About.php b/app/widgets/About/About.php new file mode 100644 index 000000000..189b6f6ea --- /dev/null +++ b/app/widgets/About/About.php @@ -0,0 +1,123 @@ + + * + * @version 1.0 + * @date 3 may 2012 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class About extends WidgetBase +{ + function WidgetLoad() { + } + + function build() + { + ?> +
+

Movim is an XMPP-based communication platform. All the project, except the following software and resources, is under + GNU Affero General Public License v3. +

+

+
+
Developers
Jaussoin Timothée aka edhelas
+
Ho Christine aka nodpounod
+
Pasquet Guillaume aka Etenil
+
Translators
Arabic - Ahmad Gharbeia أحمد غربية
+
Brazilian - millemiglia
+
Chinese - dudumomo
+
Danish - Ole Carlsen
+
Dutch - Laurens Debackere
+
English UK - Kevin Beynon, Vincent
+
Esperanto - Eliovir
+
Finish - Timo
+
French - + Hyogapag, + Hélion du Mas des Bourboux, + JonathanMM, + Ludovic Grossard, + Schoewilliam, + Vincent, + edhelas, + pou +
+
German - + Daniel Winzen, + Jonas Ehrhard, + Jonatan Zeidler, + Kilian Holzinger, +
+
Greek - + Rotaru Dorin, + aitolos +
+
Hebrew - GenghisKhan
+
Hungarian - Baptiste Darthenay
+
Italian - + Andrea Caratti, + Giacomo Alzetta, + kimj +
+
Japanese - Franky
+
Occitan (post 1500) - + Cédric VALMARY (Tot en òc), + Maime +
+
Portuguese - + JonathanMM, + millemiglia +
+
Russian - + Aleksey Kabanov, + Vyacheslav Sharmanov, + hailaga, + Сергей Сальников, + DeforaD +
+
Spanish - + Alejandro Serrano González, + Eduardo Alberto Calvo, + Esteban Mainieri, + Oizem Mushroom, + Ricardo Sánchez Baamonde, + Ubuntu, + orochiforja +
+
Turkish - + Caner Başaran, + emre akça +
+
+ +

+
+
Database Library
Modl - Movim DB Layer launchpad.net/modl under AGPLv3
+
XMPP Library
Moxl - Movim XMPP Library launchpad.net/moxl under AGPLv3
+
+
+
+
Map Library
Leaflet leafletjs.com under BSD
+
Markdown
Michel Fortin michelf.ca ©Michel Fortin
+
HTML Fixer
Giulio Pons barattalo.it
+
+

+
+
Icons
Famfamfam www.famfamfam.com under CC BY 3.0
+
Icomoon by Keyamoon under CC BY 3.0
+
+
+ + * + * @version 1.0 + * @date 25 November 2011 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Account extends WidgetBase { + + function WidgetLoad() + { + $this->addcss('account.css'); + $this->addjs('account.js'); + } + + function ajaxDiscoverServer($ndd) { + if($ndd['ndd'] == '') { + RPC::call('movim_reload', BASE_URI."index.php?q=account&err=datamissing"); + RPC::commit(); + exit; + } + + + try { + $dns = dns_get_record('_xmpp-client._tcp.'.$ndd['ndd']); + + if(isset($dns[0]['target']) && $dns[0]['target'] != null) + $domain = $dns[0]['target']; + + $f = fsockopen($domain, 5222, $errno, $errstr, 10); + + if(!$f) { + RPC::call('movim_reload', BASE_URI."index.php?q=account&err=xmppconnect"); + RPC::commit(); + exit; + } + + $stream = simplexml_load_string(''); + $stream->addAttribute('to', $ndd['ndd']); + fwrite($f, $stream->asXML()); + + unset($stream); + + $response = stream_get_contents($f); + + if(!$response) { + RPC::call('movim_reload', BASE_URI."index.php?q=account&err=xmppcomm"); + RPC::commit(); + exit; + } + + $response = simplexml_load_string($response); + + $id = (string)$response->attributes()->id; + + $elements = (array)$response->iq->query; + + // We close properly our first register request + $stream = simplexml_load_string(''); + $stream->addAttribute('to', $ndd['ndd']); + fwrite($f, $stream->asXML()); + + fclose($f); unset($f); + + if(!empty($elements)) { + $html .= ' +
+
+ '.t('Step 2 - Fill in your informations').'


'; + + if($response->iq->query->instructions && $response->iq->query->x) { + $instr = ' +
+ '; + if($response->iq->query->x->url) + $instr .= ' + '. + (string)$response->iq->query->x->url.' + '; + + $instr .= ' +
'; + + } + + $form = new XMPPtoForm(); + if(!empty($response->iq->query->x)){ + $formh .= $form->getHTML($response->iq->query->x->asXML()); + } else{/*no element in the XML*/ + $formh .= $form->getHTML($response->iq->query->asXML()); + } + + if($formh == '') + $html .= $instr; + else + $html .= $formh; + + $html .= ' + + '; + + $html .= ' + + '; + + $html .= ' + + '; + + if(isset($elements['data'])) { + $html .= ''; + } + + $submit = $this->genCallAjax('ajaxSubmitData', "movim_parse_form('data')"); + + $html .= ' + + '.t('Validate').' + '; + + $html .= ' +
+
'; + + RPC::call('movim_fill', 'fillform', $html); + RPC::commit(); + + } + else { + $html = ' +
+ '.t('No account creation form founded on the server').' +
'; + + RPC::call('movim_fill', 'fillform', $html); + RPC::commit(); + } + + } catch(Exception $e) { + header(sprintf('HTTP/1.1 %d %s', $e->getCode(), $e->getMessage())); + header('Content-Type: text/plain; charset=utf-8'); + echo $e->getMessage(),"\n"; + } + } + + function ajaxSubmitData($datas) { + + define(XMPP_HOST, $datas['to']); + define(XMPP_CONN, $datas['ndd']); + + unset($datas['to']); + unset($datas['ndd']); + //unset($datas['id']); + + define(XMPP_PORT, 5222); + + try { + // We try to connect to the XMPP Server + $f = fsockopen(XMPP_CONN, XMPP_PORT, $errno, $errstr, 10); + + if(!$f) { + RPC::call('movim_reload', BASE_URI."index.php?q=account&err=xmppconnect"); + RPC::commit(); + exit; + } + + // We create the XML Stanza + $stream = simplexml_load_string(''); + + unset($datas['id']); + + $stream->addAttribute('to', XMPP_HOST); + + $xmpp = new FormtoXMPP(); + $stream = $xmpp->getXMPP($stream->asXML(), $datas); + +\movim_log($stream->asXML()); + fwrite($f, $stream->asXML()); + unset($stream); + + $response = stream_get_contents($f); + + if(!$response) { + RPC::call('movim_reload', BASE_URI."index.php?q=account&err=xmppcomm"); + RPC::commit(); + exit; + } + + fclose($f); unset($f); + + $response = simplexml_load_string($response); +\movim_log($response); + if(!$response) throw new Exception('The XMPP server sent an invalid response', 500); + + if($stream_error = $response->xpath('/stream:stream/stream:error')) { + list($stream_error) = $stream_error; + list($cond) = $stream_error->children(); + + throw new Exception($stream_error->text ? $stream_error->text : $cond->getName(), 500); + } + + $iq = $response->iq; + + if($iq->error) { + list($cond) = $iq->error->children(); + if($cond->getName() == 'conflict') { + RPC::call('movim_reload', BASE_URI."index.php?q=account&err=userconflict"); + RPC::commit(); + exit; + } else if($cond->getName() == 'not-acceptable') { + RPC::call('movim_reload', BASE_URI."index.php?q=account&err=notacceptable"); + RPC::commit(); + exit; + } + throw new Exception($iq->error->text ? $iq->error->text : $cond->getName(), 400); + } + + if($iq = $response->iq and $iq->attributes()->type == 'result') { + RPC::call('movim_reload', BASE_URI."index.php?q=login&err=acccreated"); + RPC::commit(); + exit; + } else { + RPC::call('movim_reload', BASE_URI."index.php?q=account&err=unknown"); + RPC::commit(); + exit; + } + } catch(Exception $e) { + header(sprintf('HTTP/1.1 %d %s', $e->getCode(), $e->getMessage())); + header('Content-Type: text/plain; charset=utf-8'); + echo $e->getMessage(),"\n"; + } + } + + function printServerList() { + $file = dirname(__FILE__).DIRECTORY_SEPARATOR.'server-vcards.xml'; + + $html = ''; + + if(file_exists($file)) { + $vcards = simplexml_load_file($file); + + $html .= ' +
+ + + + + + + + + + + '; + + $markers = array(); + foreach($vcards as $vcard) { + $name = (string)$vcard->fn->text; + $html .=' + + + + + + + + '; + $coord = explode("geo:", $vcard->geo->uri); + if(isset($coord[1])){ + $split = explode(",", $coord[1]); + $newkey = round(floatval($split[0]),1).",".round(floatval($split[1]),1); + if(!isset($markers[$newkey])){ + $markers[$newkey] = array($name); + } + else{ + array_push($markers[$newkey], $name); + } + } + } + + $html .= ' + +
+ '.t('Name').' + + '.t('Description').' + + '.t('URL').' + + '.t('Software').' + +
+ '.$name.' + + '.(string)$vcard->note->text.' + + + '.(string)$vcard->url->uri.' + + + '.(string)$vcard->name.' + + '.(string)$vcard->adr->country.' +
'; + + $javascript = ''; + } + + return $javascript.$html; + } + + function build() + { + switch ($_GET['err']) { + case 'datamissing': + $warning = ' +
+ '.t('Some data are missing !').' +
'; + break; + case 'jiderror': + $warning = ' +
+ '.t('Wrong ID').' +
'; + break; + case 'passworddiff': + $warning = ' +
+ '.t('You entered different passwords').' +
'; + break; + case 'nameerr': + $warning = ' +
+ '.t('Invalid name').' +
'; + break; + case 'notacceptable': + $warning = ' +
+ '.t('Request not acceptable').' +
'; + break; + case 'userconflict': + $warning = ' +
+ '.t('Username already taken').' +
'; + break; + case 'xmppconnect': + $warning = ' +
+ '.t('Could not connect to the XMPP server').' +
'; + break; + case 'xmppcomm': + $warning = ' +
+ '.t('Could not communicate with the XMPP server').' +
'; + break; + case 'unknown': + $warning = ' +
+ '.t('Unknown error').' +
'; + break; + } + + $submit = $this->genCallAjax('ajaxDiscoverServer', "movim_parse_form('account')"); + ?> +
+
+ +
+
+

+
+

+ + +

+
+
+
+ +
+

+ ', ''); + echo t('Or you can choose a server from this list.'); ?> +

+
+ +
+ +
+ printServerList(); ?> + +
+
+ + " + name="ndd" + id="ndd" + /> +
+ +
+ + + + + + +
+
+
+
+
+ + + + movim.eu + + + application + + + http://movim.eu/ + + + The Movim XMPP service. + + + xmpp:movim.eu + + + 2013 + + + IE + + + CAcert + http://www.cacert.org/ + + Metronome + + xmpp:edhelas@movim.eu + + + geo:53.06,-7.29 + + + + + jappix.com + + + application + + + http://jappix.com/ + + + The Jappix XMPP service. + + + xmpp:jappix.com + + + 2010 + + + FR + + + CAcert + http://www.cacert.org/ + + Metronome + + xmpp:vanaryon@jappix.com + + + geo:50.67,3.19 + + + + + tigase.im + + + application + + + http://www.tigase.im/ + + + The public Tigase service. - Also supports IPv6! + + + xmpp:tigase.im + + + 2010 + + + EU + + + StartSSL + http://www.startssl.com/ + + Tigase + + xmpp:admin@im.flosoft.biz + + + geo:50.69,3.19 + + + + + lightwitch.org + + + application + + + http://www.lightwitch.org/ + + + LW.Org XMPP Public Service. + + + xmpp:lightwitch.org + + + 2009 + + + USA + + + StartSSL + http://www.startssl.com/ + + Metronome + + xmpp:maranda@lightwitch.org + + + geo:40.73,-74.17 + + + + + jabber.me + + + application + + + http://www.jabber.me/ + + + Just Jabber Me! - Also supports IPv6! + + + xmpp:jabber.me + + + 2010 + + + EU + + + StartSSL + http://www.startssl.com/ + + Tigase + + xmpp:admin@im.flosoft.biz + + + geo:50.69,3.19 + + + + + sure.im + + + application + + + http://www.sure.im/ + + + Just Sure Im! - Also supports IPv6! + + + xmpp:sure.im + + + 2010 + + + EU + + + StartSSL + http://www.startssl.com/ + + Tigase + + xmpp:admin@im.flosoft.biz + + + geo:50.69,3.19 + + + + + jabbim.cz + + + application + + + http://www.jabbim.cz/ + + + Stable ejabberd clustered server with good support and many transports and services: ICQ, AIM, MSN, Facebook, Weather, Yahoo, Notes, bots, MUCs, proxy65, STUN server for voice support, and more + + + xmpp:jabbim.cz + + + 2005 + + + CZ + + + CAcert + http://www.cacert.org/ + + ejabberd + + xmpp:pinky@njs.netlab.cz + + + njs.netlab.czapplicationhttp://www.jabbim.cz/Public service hosted by jabbim.czxmpp:njs.netlab.cz2001CZCAcerthttp://www.cacert.org/ejabberdxmpp:pinky@njs.netlab.cz + jabbim.plapplicationhttp://www.jabbim.cz/Public service hosted by jabbim.czxmpp:jabbim.pl2005CZCAcerthttp://www.cacert.org/ejabberdxmpp:pinky@njs.netlab.cz + jabbim.skapplicationhttp://www.jabbim.cz/Public service hosted by jabbim.czxmpp:jabbim.sk2005CZCAcerthttp://www.cacert.org/ejabberdxmpp:pinky@njs.netlab.cz + jabbim.comapplicationhttp://www.jabbim.cz/Public service hosted by jabbim.czxmpp:jabbim.com2005CZCAcerthttp://www.cacert.org/ejabberdxmpp:pinky@njs.netlab.cz + forumanalogue.frapplicationhttp://www.forumanalogue.fr/A public self-hosted Jabber server located in France.xmpp:forumanalogue.fr2010FRStartSSLhttp://www.startssl.com/Openfirexmpp:clement@forumanalogue.frgeo:45.8,4.841fr + + + + + diff --git a/app/widgets/Admin/Admin.php b/app/widgets/Admin/Admin.php new file mode 100644 index 000000000..de392a092 --- /dev/null +++ b/app/widgets/Admin/Admin.php @@ -0,0 +1,484 @@ + + * + * @version 1.0 + * @date 25 November 2011 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Admin extends WidgetBase { + private $_conf; + + function WidgetLoad() + { + $this->_conf = Conf::getServerConf(); + } + + private function isValid($what) + { + if($what) + return "message success"; + else + return "message error"; + } + + private function testDir($dir){ + return (file_exists($dir) && is_dir($dir) && is_writable($dir)); + } + + private function testFile($file) { + return (file_exists($file) && is_writable($file)); + } + + /* + * Create the dirs + */ + function createDirs(){ + if(!file_exists(BASE_PATH.'cache') && !@mkdir(BASE_PATH.'cache')) { + echo t("Couldn't create directory '%s'.", 'cache'); + return false; + } + + if(!file_exists(BASE_PATH.'log') && !@mkdir(BASE_PATH.'log')) { + echo t("Couldn't create directory '%s'.", 'log'); + return false; + } + + if(!file_exists(BASE_PATH.'config') && !@mkdir(BASE_PATH.'config')) { + echo t("Couldn't create directory '%s'.", 'config'); + return false; + } + } + + private function listThemes() + { + $dir = opendir(BASE_PATH.'themes'); + $themes = array(); + + while($theme = readdir($dir)) { + if(preg_match('/^\.+$/', $theme) + || !is_dir(BASE_PATH.'themes/'.$theme)) { + continue; + } + + $themes[$theme] = $theme; + } + + return $themes; + } + + private function listLangs() + { + $dir = opendir(BASE_PATH.'i18n'); + $langs = array('en' => 'English'); + $languages = get_lang_list(); + + while($lang = readdir($dir)) { + if(!preg_match('/\.po$/', $lang)) { + continue; + } + + $lang = substr($lang, 0, strlen($lang) - 3); + $langs[$lang] = $languages[$lang]; + } + + return $langs; + } + + function testBosh($url) { + $ch = curl_init($url); + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate'); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + + // Fire ! + $rs = array(); + + $rs['content'] = curl_exec($ch); + $rs['errno'] = curl_errno($ch); + $rs['errmsg'] = curl_error($ch); + $rs['header'] = curl_getinfo($ch); + + if($rs['content'] != false && $rs['content'] != '') { + return true; + } + + elseif($rs['errno'] != 0 || $rs['content'] == '') { + return false; + } + curl_close($ch); + } + + public function ajaxAdminSubmit($form) + { + unset($form['']); + + $empty = false; + + if($form['pass'] == '' || !isset($form['pass'])) { + $form['pass'] = $this->_conf['pass']; + $form['repass'] = $this->_conf['pass']; + + $empty = true; + } + + if($form['pass'] == $form['repass']) { + unset($form['repass']); + + if(!$empty) + $form['pass'] = sha1($form['pass']); + + foreach($this->_conf as $key => $value) { + if(isset($form[$key])) + $this->_conf[$key] = $form[$key]; + } + + Conf::saveConfFile($this->_conf); + } + } + + public function ajaxRecreateDatabase() + { + $pd = new \modl\PostnDAO(); + $pd->create(); + + $nd = new \modl\NodeDAO(); + $nd->create(); + + $cd = new \modl\ContactDAO(); + $cd->create(); + + $cad = new \modl\CapsDAO(); + $cad->create(); + + $prd = new \modl\PresenceDAO(); + $prd->create(); + + $rd = new \modl\RosterLinkDAO(); + $rd->create(); + + $sd = new \modl\SessionDAO(); + $sd->create(); + + $cd = new \modl\CacheDAO(); + $cd->create(); + + $md = new \modl\MessageDAO(); + $md->create(); + + $cd = new \modl\SubscriptionDAO(); + $cd->create(); + + $pr = new \modl\PrivacyDAO(); + $pr->create(); + } + + private function prepareAdmin() + { + $submit = $this->genCallAjax('ajaxAdminSubmit', "movim_parse_form('admin')") + ."this.className='button icon loading'; setTimeout(function() {location.reload(false)}, 2000);"; + + if($this->testDir(BASE_PATH)) + $this->createDirs(); + + $html = ' +
'; + + /*$html .= ' +
+ '.t('General Informations').''; + + $file = BASE_PATH.'VERSION'; + if($f = fopen($file, 'r')){ + $html .= ' +
+ + '.trim(fgets($f)).' +
'; + } + + $html .= ' +
';*/ + + $html .= ' +
+ '.t("Compatibility Check").' +
'; + + $html .= + '

'. + t('Movim requires certain external components. Please install them before you can succeed:'). + '


'; + + $html .= ' +
+ '.t('Your PHP-Version: %s
Required: 5.3.0', PHP_VERSION).' +
+
+ '.t('CURL-Library').' +
+
+ '.t('GD').' +
+
+ '.t('SimpleXML').' +
+
+ '.t('Read and write rights for the webserver in Movim\'s root directory').' +
+
+ '.t('URL Rewriting support').' +
'; + + $html .= ' +
'; + + $html .= ' +
+ '.t('General Settings').' +
+ +
+ +
+
'; + + $html .= ' +
+ +
+ +
+
'; + + $html .= ' +
+ + +
'; + + $html .= ' +
+ + +
'; + + $logopts = array( + 0 => t('empty'), + 2 => t('terse'), + 4 => t('normal'), + 6 => t('talkative'), + 7 => t('ultimate'), + ); + + $default_log = 4; + + $html .= ' +
+ +
+ +
+
'; + + $html .= ' +
+ '.t('Submit').''; + + $html .= ' +
'; + + $html .= ' +
+ '.t("Database Settings").' +
'; + + $md = new \modl\ModlDAO(); + if(isset($md->_dao->_error)) { + $html .= ' +
'. + t("Modl wasn't able to connect to the database").'
+ '.$md->_dao->_error.' +
+ '; + } else { + $dbrecreate = $this->genCallAjax('ajaxRecreateDatabase'); + + $html .= ' +
+ + '.t('Recreate').' +
+ +
+ '.t('This button will clear and recreate the Movim database.').' +
+ '; + } + + $html .= ' +
+ + +
'; + + $html .= ' +
+ '.t('Submit').''; + + $html .= ' +
'; + + $html .= ' +
+ '.t("Bosh Configuration").' +
'; + + $html .= '

'. + t("Enter here the BOSH-URL in the form: http(s)://domain:port/path.").' '. + t('If you enter an open BOSH-Server, you can connect to many XMPP-Servers.').' '. + t('If it is closed, you have to specify the corresponding Server on the next page.').' '. + t('If you are unsure about this config option visit the wiki'); + '

'; + + if(!$this->testBosh($this->_conf['boshUrl'])) { + $html .= ' +
'. + t('Your Bosh URL is not reachable').' +
'; + } + + $html .= ' +
+ + +
'; + + $html .= ' +
+ '.t('Submit').''; + + $html .= ' +
'; + + $html .= ' +
+ '.t("Whitelist - XMPP Server").' +
'; + + $html .= '

'. + t("If you want to specify a list of authorized XMPP servers on your Movim pod and forbid the connection on all the others please put their domain name here, with comma (ex: movim.eu,jabber.fr)"). + '

'. + '

'. + t("Leave this field blank if you allow the access to all the XMPP accounts."). + '

'; + + $html .= ' +
+ + +
'; + + $html .= ' +
+ '.t('Submit').''; + + $html .= ' +
'; + + $html .= ' +
+ '.t("Administration Credential").''; + + if($this->_conf['user'] == 'admin' && $this->_conf['pass'] == sha1('password')) { + $html .= ' +
'. + t('Change the default username/password').' +
'; + } + + $html .= ' +
+ + +
+
+ +
+ + +
+
+ + +
'; + + $html .= ' +
+ '.t('Submit').''; + + $html .= ' +
'; + + $html .= ' +
'; + + return $html; + } + + function build() + { + ?> +
+ prepareAdmin(); ?> +
+ getPublic($from); + + echo ' + '; + + echo $this->preparePosts($messages, true); + } +} diff --git a/app/widgets/Bookmark/Bookmark.php b/app/widgets/Bookmark/Bookmark.php new file mode 100644 index 000000000..b1f85a207 --- /dev/null +++ b/app/widgets/Bookmark/Bookmark.php @@ -0,0 +1,280 @@ + + * + * @version 1.0 + * @date 28 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Bookmark extends WidgetBase +{ + function WidgetLoad() + { + $this->addcss('bookmark.css'); + $this->registerEvent('bookmark', 'onBookmark'); + $this->registerEvent('bookmarkerror', 'onBookmarkError'); + $this->registerEvent('groupsubscribed', 'onGroupSubscribed'); + $this->registerEvent('groupunsubscribed', 'onGroupUnsubscribed'); + } + + function onGroupSubscribed() + { + $arr = Cache::c('bookmark'); + + $html = $this->prepareBookmark($arr); + RPC::call('movim_fill', 'bookmarks', $html); + RPC::call('setBookmark'); + } + + function onGroupUnsubscribed() + { + $arr = Cache::c('bookmark'); + + $html = $this->prepareBookmark($arr); + RPC::call('movim_fill', 'bookmarks', $html); + RPC::call('setBookmark'); + } + + function onBookmark($arr) + { + $i = 0; + foreach($arr as $b) { + if($b['type'] == 'subscription') { + $su = new \modl\Subscription(); + $su->jid = $this->user->getLogin(); + $su->server = $b['server']; + $su->node = $b['node']; + $su->subscription = 'subscribed'; + $su->subid = $b['subid']; + $su->timestamp = date('Y-m-d H:i:s', rand(1111111111, 8888888888)); + + $sd = new \modl\SubscriptionDAO(); + $sd->set($su); + + unset($arr[$i]); + } + $i++; + } + + Cache::c('bookmark', $arr); + $html = $this->prepareBookmark($arr); + RPC::call('movim_fill', 'bookmarks', $html); + Notification::appendNotification(t('Bookmarks updated'), 'info'); + } + + function onBookmarkError($error) + { + Notification::appendNotification(t('An error occured : ').$error, 'error'); + } + + function ajaxGetBookmark() + { + $b = new moxl\BookmarkGet(); + $b->request(); + } + + function ajaxSetBookmark($arr = null) + { + if($arr == null || $arr == '') + $arr = Cache::c('bookmark'); + if($arr == null) + $arr = array(); + + $sd = new \modl\SubscriptionDAO(); + + if($sd != null) { + foreach($sd->getSubscribed() as $s) { + array_push($arr, + array( + 'type' => 'subscription', + 'server' => $s->server, + 'title' => $s->title, + 'subid' => $s->subid, + 'node' => $s->node)); + } + } + + $b = new moxl\BookmarkSet(); + $b->setArr($arr) + ->request(); + } + + function ajaxBookmarkAdd($form) + { + if(!filter_var($form['url'], FILTER_VALIDATE_URL)) { + $html = '
'.t('Bad URL').'
' ; + RPC::call('movim_fill', 'bookmarkadderror', $html); + RPC::commit(); + } elseif(trim($form['name']) == '') { + $html = '
'.t('Empty name').'
' ; + RPC::call('movim_fill', 'bookmarkadderror', $html); + RPC::commit(); + } else { + + $bookmarks = Cache::c('bookmark'); + + if($bookmarks == null) + $bookmarks = array(); + + array_push($bookmarks, + array( + 'type' => 'url', + 'name' => $form['name'], + 'url' => $form['url'])); + + $this->ajaxSetBookmark($bookmarks); + } + } + + function ajaxBookmarkUrlRemove($url) + { + $arr = Cache::c('bookmark'); + foreach($arr as $key => $b) { + if($b['type'] == 'url' && $b['url'] == $url) + unset($arr[$key]); + } + + $b = new moxl\BookmarkSet(); + $b->setArr($arr) + ->request(); + } + + function prepareBookmark($bookmarks) + { + $html = ''; + $url = ''; + $conference = ''; + $subscription = ''; + + $sd = new \modl\SubscriptionDAO(); + + if($sd != null) { + + foreach($sd->getSubscribed() as $s) { + $subscription .= ' +
  • + '. + $s->node.' ('.$s->server.') + +
  • '; + } + } + + if($bookmarks == null) + $bookmarks = array(); + + foreach($bookmarks as $b) { + switch ($b['type']) { + case 'conference': + $conference .= ' +
  • '.$b['name'].'
  • '; + break; + case 'url': + $remove = $this->genCallAjax('ajaxBookmarkUrlRemove', "'".$b['url']."'"); + $url .= ' +
  • + '. + $b['name'].' + + X +
  • '; + break; + } + } + + if($subscription != '') { + $html .= ' +

    '.t('Groups').'

    + '; + } + + if($url != '') { + $html .= ' +

    '.t('Links').'

    + '; + } + + if($conference != '') { + $html .= ' +

    '.t('Conferences').'

    + '; + } + + $submit = $this->genCallAjax('ajaxBookmarkAdd', "movim_parse_form('bookmarkadd')"); + + $html .= ' + + '; + + return $html; + } + + function build() + { + $getbookmark = $this->genCallAjax("ajaxGetBookmark"); + $setbookmark = $this->genCallAjax("ajaxSetBookmark", "''"); + ?> + + +

    + +
    + prepareBookmark(Cache::c('bookmark')); ?> +
    +
    + + +
    + + * + * @version 1.0 + * @date 20 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Chat extends WidgetBase +{ + function WidgetLoad() + { + $this->addcss('chat.css'); + $this->addjs('chat.js'); + $this->registerEvent('message', 'onMessage'); + $this->registerEvent('messagepublished', 'onMessagePublished'); + $this->registerEvent('composing', 'onComposing'); + $this->registerEvent('paused', 'onPaused'); + $this->registerEvent('attention', 'onAttention'); + $this->registerEvent('presence', 'onPresence'); + } + + function onPresence($presence) + { + $arr = $presence->getPresence(); + + $rc = new \modl\ContactDAO(); + $contact = $rc->getRosterItem(echapJid($jid)); + + if(isset($contact) && $contact->chaton == 1) { + $txt = array( + 1 => t('Online'), + 2 => t('Away'), + 3 => t('Do Not Disturb'), + 4 => t('Extended Away'), + 5 => t('Offline'), + ); + + + $html = ' +
    + '.date('G:i', time()).''. + prepareString(htmlentities($txt[$arr['presence']], ENT_COMPAT, "UTF-8")).' +
    '; + + RPC::call('movim_append', + 'messages'.$arr['jid'], + $html); + + RPC::call('scrollTalk', + 'messages'.$arr['jid']); + } + } + + function onMessage($message) + { + if($message->key == $message->from) { + $key = $message->from; + $jid = $message->to; + } else { + $key = $message->to; + $jid = $message->from; + } + + if($message->key != $message->from) + RPC::call('notify'); + + $rd = new \modl\RosterLinkDAO(); + + $rc = new \modl\ContactDAO(); + $contact = $rc->getRosterItem(echapJid($jid)); + + if(isset($contact) && $contact->chaton == 0) { + $contact->chaton = 2; + $rd->setChat($jid, 2); + + $evt = new Event(); + $evt->runEvent('openchat'); + + RPC::call('movim_prepend', + 'chats', + $this->prepareChat($contact)); + RPC::call('scrollAllTalks'); + } else if(isset($contact) && $message->body != '') { + $html = $this->prepareMessage($message); + + if($contact->chaton == 1) { + RPC::call('colorTalk', + 'messages'.$contact->jid); + } + + RPC::call('movim_append', + 'messages'.$contact->jid, + $html); + + RPC::call('hideComposing', + $contact->jid); + + RPC::call('hidePaused', + $contact->jid); + + RPC::call('scrollTalk', + 'messages'.$contact->jid); + } + } + + function onMessagePublished($jid) + { + Notification::appendNotification(t('Message Published'), 'success'); + } + + function onComposing($jid) + { + $rd = new \modl\RosterLinkDAO(); + $contact = $rd->get(echapJid($jid)); + + if(in_array($contact->chaton, array(1, 2))) { + RPC::call('showComposing', + $contact->jid); + + RPC::call('scrollTalk', + 'messages'.$contact->jid); + } + } + + function onPaused($jid) + { + $rd = new \modl\RosterLinkDAO(); + $contact = $rd->get(echapJid($jid)); + + if(in_array($contact->chaton, array(1, 2))) { + RPC::call('showPaused', + $contact->jid); + + RPC::call('scrollTalk', + 'messages'.$contact->jid); + } + } + + function onAttention($jid) + { + $rc = new \modl\ContactDAO(); + $contact = $rc->getRosterItem(echapJid($jid)); + + $html = ' +
    + '.date('G:i', time()).''. + t('%s needs your attention', $contact->getTrueName()).' +
    '; + + RPC::call('movim_append', + 'messages'.$jid, + $html); + + RPC::call('scrollTalk', + 'messages'.$jid); + } + + + /** + * Open a new talk + * + * @param string $jid + * @return void + */ + function ajaxOpenTalk($jid) + { + $rc = new \modl\ContactDAO(); + $contact = $rc->getRosterItem(echapJid($jid)); + + if( + isset($contact) + && $contact->chaton == 0 + && !in_array($contact->presence, array(5, 6))) { + + $contact->chaton = 2; + + $rd = new \modl\RosterLinkDAO(); + $rd->setChat($jid, 2); + + RPC::call('movim_prepend', + 'chats', + $this->prepareChat($contact)); + + RPC::call('scrollAllTalks'); + + RPC::commit(); + } + + $evt = new Event(); + $evt->runEvent('openchat'); + } + + /** + * Send a message + * + * @param string $to + * @param string $message + * @return void + */ + function ajaxSendMessage($to, $message) + { + $m = new \modl\Message(); + + $m->key = $this->user->getLogin(); + $m->to = echapJid($to); + $m->from = $this->user->getLogin(); + + $m->type = 'chat'; + + $m->body = rawurldecode($message); + + $m->published = date('Y-m-d H:i:s'); + $m->delivered = date('Y-m-d H:i:s'); + + $md = new \modl\MessageDAO(); + $md->set($m); + + $evt = new Event(); + $evt->runEvent('message', $m); + + // We decode URL codes to send the correct message to the XMPP server + $m = new \moxl\MessagePublish(); + $m->setTo($to) + ->setContent(htmlspecialchars(rawurldecode($message))) + ->request(); + } + + /** + * Send a "composing" message + * + * @param string $to + * @return void + */ + function ajaxSendComposing($to) + { + $mc = new \moxl\MessageComposing(); + $mc->setTo($to) + ->request(); + } + + /** + * Send a "paused" message + * + * @param string $to + * @return void + */ + function ajaxSendPaused($to) + { + $mp = new \moxl\MessagePaused(); + $mp->setTo($to) + ->request(); + } + + /** + * Close a talk + * + * @param string $jid + * @return void + */ + function ajaxCloseTalk($jid) + { + $rd = new \modl\RosterLinkDAO(); + $contacts = $rd->getChats(); + + foreach($contacts as $contact) { + if( + $contact->jid == $jid + && ( + (int)$contact->chaton == 1 + || (int)$contact->chaton == 2) + ) { + $contact->chaton = 0; + $rd->setNow($contact); + } + } + + RPC::call('movim_delete', + 'chat'.$jid); + + $evt = new Event(); + $evt->runEvent('closechat'); + } + + function ajaxHideTalk($jid) + { + $rd = new \modl\RosterLinkDAO(); + $contact = $rd->get(echapJid($jid)); + + if($contact->chaton == 1) + $contact->chaton = 2; + else + $contact->chaton = 1; + $rd->setNow($contact); + + RPC::call('scrollTalk', + 'messages'.$contact->jid); + RPC::commit(); + } + + function prepareMessage($message) { + if($message->body != '') { + $html = '
    body)) { + $html .= " own "; + $content = "** ".substr($message->body, 4); + } + + $html .= '">'.date('H:i', strtotime($message->published)).''; + $html.= prepareString(htmlentities($content, ENT_COMPAT, "UTF-8")).'
    '; + return $html; + } else { + return ''; + } + } + + function prepareChats() + { + $rc = new \modl\ContactDAO(); + $contacts = $rc->getRosterChat(); + + if(isset($contacts)) { + foreach($contacts as $contact) { + $html .= trim($this->prepareChat($contact)); + } + } + + return $html; + } + + function prepareChat($contact) + { + $md = new \modl\MessageDAO(); + $messages = $md->getContact($contact->jid, 0, 10); + + if(!empty($messages)) { + $day = ''; + foreach($messages as $m) { + if($day != date('d',strtotime($m->published))) { + $messageshtml .= '
    '.prepareDate(strtotime($m->published), false).'
    '; + $day = date('d',strtotime($m->published)); + } + $messageshtml .= $this->prepareMessage($m); + } + } + + $style = ''; + if($contact->chaton == 2) { + $tabstyle = ' style="display: none;" '; + $panelstyle = ' style="display: block;" '; + } + + $html = ' +
    +
    +
    + jid."'").'"> + jid."'").' hideTalk(this)"> + + + '.$contact->getTrueName().' + +
    +
    + '.$messageshtml.' + + +
    + +
    + +
    +
    + +
    jid."'").' showTalk(this);"> +
    + '.$contact->getTrueName().' +
    +
    +
    + + '; + return $html; + } + + function build() + { + echo '
    '; + echo $this->prepareChats(); + echo '
    '; + } +} diff --git a/app/widgets/Chat/chat.css b/app/widgets/Chat/chat.css new file mode 100644 index 000000000..50801fa17 --- /dev/null +++ b/app/widgets/Chat/chat.css @@ -0,0 +1,181 @@ +#chats { + position: fixed; + bottom: -4px; + right: 210px; + z-index: 3; +} + +#chats .chat { + display: inline-block; + position: relative; + bottom: 0; + overflow: hidden; + margin-left: 0.5em; +} + +#chats .chat .panel { + display: none; +} + +#chats .chat .tab { + background-color: #272727; + color: white; +} + +#chats .chat .tab.alert .name { + display: relative; +} + +#chats .chat .tab.alert .name:after { + content: "+1"; + color: white; + font-size: 10px; + padding: 0px; + line-height: 1.7em; + float: right; + background-color: #C5371E; + margin-top: 3px; + padding: 0px 8px; + margin-left: 10px; +} + +#chats .chat .tab:hover { + background-color: #333; +} + +#chats .chat .tab .name { + line-height: 2em; + padding-right: 0.5em; +} + +#chats .chat .tab .name img { + float: left; + margin-right: 0.5em; +} + +#chats .chat .tab:hover { + cursor: pointer; +} + +#chats .chat .panel { + background-color: white; + width: 225px; +} + +#chats .chat .panel .head { + background-color: #272727; + height: 2em; +} + + +#chats .chat .panel .head span.chatbutton { + width: 0px; + height: 0px; + display: block; + background-position: center center; + background-repeat: no-repeat; + padding: 1em; + float: right; +} + +#chats .chat .panel .head span.chatbutton:hover { + background-color: #333; +} + +#chats .chat .panel .head span.chatbutton.cross { + background-image: url(img/cross.png); +} + +#chats .chat .panel .head span.chatbutton.arrow { + background-image: url(img/arrow.png); +} + +#chats .chat .panel .head a.name { + padding-right: 0.5em; + line-height: 2em; + display: inline-block; + margin: 0px; + width: 120px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#chats .chat .panel .head:hover { + cursor: pointer; +} + +#chats .chat .panel .head > * { + color: white; +} + +#chats .chat .panel .head a:hover { + text-decoration: underline; +} + +#chats .chat .panel .head img { + margin-right: 0.5em; + float: left; +} + +#chats .chat .panel .messages { + background-color: white; + color: gray; + max-height: 250px; + overflow: auto; + min-height: 3em; + border: 1px solid #888; + border-top: 0px; + border-bottom: 0px; +} + +#chats .chat .panel .text { + overflow: hidden; + border: 1px solid #888; +} + +#chats .chat .panel .text textarea { + width: 100%; + border: 0px; + padding: 0.2em; + overflow: auto; + background-color: white; + resize: none; + font-size: 1em; + height: 1.3em; + overflow-y: hidden; +} + +#chats .chat .panel .text textarea:focus { + border: 0px; +} + +#chats .chat .panel .messages .message { + padding: 5px; + word-wrap: break-word; + font-size: 12px; +} + +#chats .chat .panel .messages .message.me { + background-color: #FFC; +} + +#chats .chat .panel .messages .message.own { + color: blue; +} + +#chats .chat .panel .messages .message.presence { + color: black; + font-weight: bold; +} + +#chats .chat .panel .messages .message span.date { + float: right; + color: #ccc; + padding: 2px; + line-height: 1em; +} + +#chats .chat .panel .messages .message.me span.date { + color: #444; +} diff --git a/app/widgets/Chat/chat.js b/app/widgets/Chat/chat.js new file mode 100644 index 000000000..f31d1311c --- /dev/null +++ b/app/widgets/Chat/chat.js @@ -0,0 +1,102 @@ +function scrollAllTalks() { + var mes = document.querySelectorAll('.messages'); + for (var i=0; i2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4kh4lw}++BH_%Ys?EbY9Rc@dV~M4biMu9Jo!i4(w)-Kk#gK z%!=zZoAl1xo!`By=l)+Ynbw6L&U`TCa$cx=ka1E(^ThW5CnSOHVeoYIb6Mw<&;$T+ C=w4U= literal 0 HcmV?d00001 diff --git a/app/widgets/Chat/img/cross.png b/app/widgets/Chat/img/cross.png new file mode 100644 index 0000000000000000000000000000000000000000..8e4d76ed3e0c0318987f4844d02379884be1bbd1 GIT binary patch literal 376 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhjKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=f%E|oW;7_j9|vTxmw5WRvft(w6VqUml3MKy6p}1)jVN)>&&^HE zD`9XhN=+CPX?>pSx@zYM+H$mdPn&QuQw(9Dv6@EpNpDcX6>%B@~u$SlE`>K^* zpM)RC3cP3xbz8cwAx^Y{(}0=Hp_Kp3WR@Aszq!7JDh8S_=9GUGW*c_&Z;0W6AlvJ0 z=Xc4?4r*pHX`Ne@$$Ma%?G8iUm=)^lOC=*``RlG}bY}HC;Ai{)^O|#47RJdmxZ1|A zs`Y(2tL<0VLC0ACqI)ZxyVtK+@0oY?_qx~nmf3Th@zU(~tozRpl%ietR^$0&p!XO& MUHx3vIVCg!04u_bqyPW_ literal 0 HcmV?d00001 diff --git a/app/widgets/Chat/sound/notif.ogg b/app/widgets/Chat/sound/notif.ogg new file mode 100644 index 0000000000000000000000000000000000000000..cb12df54b66f53269a2bcc6cc2cbdc3d60eac369 GIT binary patch literal 20987 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 BD@OnT literal 0 HcmV?d00001 diff --git a/app/widgets/ChatExt/ChatExt.php b/app/widgets/ChatExt/ChatExt.php new file mode 100644 index 000000000..63ada8dbd --- /dev/null +++ b/app/widgets/ChatExt/ChatExt.php @@ -0,0 +1,150 @@ + + * + * @version 1.0 + * @date 20 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +require_once(APP_PATH . "widgets/Chat/Chat.php"); + +class ChatExt extends WidgetBase +{ + function WidgetLoad() + { + $this->addcss('chatext.css'); + $this->addjs('chatext.js'); + $this->registerEvent('message', 'onMessage'); + $this->registerEvent('openchat', 'onEvent'); + $this->registerEvent('closechat', 'onEvent'); + } + + function prepareChat($contact) + { + $md = new \modl\MessageDAO(); + $messages = $md->getContact($contact->jid, 0, 10); + + if(!empty($messages)) { + $day = ''; + foreach($messages as $m) { + if($day != date('d',strtotime($m->published))) { + $messageshtml .= '
    '.prepareDate(strtotime($m->published), false).'
    '; + $day = date('d',strtotime($m->published)); + } + $chat = new Chat(); + $messageshtml .= $chat->prepareMessage($m); + } + } + + $style = ''; + if($contact->chaton == 2) { + $tabstyle = ' style="display: none;" '; + $panelstyle = ' style="display: block;" '; + } + + $html = ' +
    +
    + '.$messageshtml.' + + +
    + +
    + +
    + +
    + '; + return $html; + } + + function prepareList($contact, $first = false) + { + if($first) + $checked = ' checked '; + $html .= ' +
  • + + +
    '.trim($this->prepareChat($contact)).' + jid."'").'"> +
    +
  • '; + return $html; + } + + function onEvent() + { + if(!Cache::c('chatpop')) { + $html = $this->preparePop(); + RPC::call('popUpEvent', 'movim_fill', 'chatpop', $html); + RPC::call('popUpEvent', 'scrollAllTalks'); + } + } + + function preparePop() + { + $rc = new \modl\ContactDAO(); + $contacts = $rc->getRosterChat(); + + $list = ''; + + if(isset($contacts)) { + $first = true; + + foreach($contacts as $contact) { + $list .= $this->prepareList($contact, $first); + $first = false; + } + $html = '
      '.$list.'
    '; + } + + return $html; + } + + function onMessage($message) + { + if($message->key == $message->from) { + $key = $message->from; + $jid = $message->to; + } else { + $key = $message->to; + $jid = $message->from; + } + + $chatpop = Cache::c('chatpop'); + if(!$chatpop) { + $chat = new Chat(); + RPC::call('popUpEvent', 'movim_append', 'messages'.$jid, $chat->prepareMessage($message)); + RPC::call('popUpEvent', 'scrollAllTalks'); + } + } + + function build() + { + + } + +} diff --git a/app/widgets/ChatExt/chatext.css b/app/widgets/ChatExt/chatext.css new file mode 100644 index 000000000..e69de29bb diff --git a/app/widgets/ChatExt/chatext.js b/app/widgets/ChatExt/chatext.js new file mode 100644 index 000000000..f7f7dd430 --- /dev/null +++ b/app/widgets/ChatExt/chatext.js @@ -0,0 +1,31 @@ +// Initialise popup pointer +var popupWin = null; + +function openPopup() { + var url = "?q=chatpop" + if( !popupWin || popupWin.closed ) { + popupWin = window.open( url, "popupWin", "height=400,width=600,directories=0,titlebar=0,toolbar=0,location=0,status=0,menubar=0,resizable=no" ); + } else popupWin.focus(); +} + +function closePopup() { + popupWin.close(); +} + +function focusPopup() { + popupWin.focus(); +} + +function popUpEvent(args) { + if( popupWin && !popupWin.closed ) { + // The popup is open so call it + var func = args[0]; + args.shift(); + var params = args; + + window['popupWin'][func](params); + } else { + // The popup is closed so open it + openPopup(); + } +} diff --git a/app/widgets/ChatPop/ChatPop.php b/app/widgets/ChatPop/ChatPop.php new file mode 100644 index 000000000..4775e4c48 --- /dev/null +++ b/app/widgets/ChatPop/ChatPop.php @@ -0,0 +1,45 @@ + + * + * @version 1.0 + * @date 20 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +require_once(APP_PATH . "widgets/ChatExt/ChatExt.php"); + +class ChatPop extends WidgetBase +{ + function WidgetLoad() + { + $this->addcss('chatpop.css'); + $this->addjs('chatpop.js'); + } + + function build() + { + $chatext = new ChatExt(); + + echo '
    '; + echo $chatext->preparePop(); + echo '
    '; + ?> +
    + +
    + &&^HE zD`9XhN=+CPX?>pSx@zYM+H$mdPn&QuQw(9Dv6@EpNpDcX6>%B@~u$SlE`>K^* zpM)RC3cP3xbz8cwAx^Y{(}0=Hp_Kp3WR@Aszq!7JDh8S_=9GUGW*c_&Z;0W6AlvJ0 z=Xc4?4r*pHX`Ne@$$Ma%?G8iUm=)^lOC=*``RlG}bY}HC;Ai{)^O|#47RJdmxZ1|A zs`Y(2tL<0VLC0ACqI)ZxyVtK+@0oY?_qx~nmf3Th@zU(~tozRpl%ietR^$0&p!XO& MUHx3vIVCg!04u_bqyPW_ literal 0 HcmV?d00001 diff --git a/app/widgets/Config/Config.php b/app/widgets/Config/Config.php new file mode 100644 index 000000000..4f7c0db43 --- /dev/null +++ b/app/widgets/Config/Config.php @@ -0,0 +1,196 @@ + + * + * @version 1.0 + * @date 28 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Config extends WidgetBase +{ + function WidgetLoad() + { + $this->addcss('config.css'); + $this->addjs('color/jscolor.js'); + $this->registerEvent('config', 'onConfig'); + } + + function onConfig(array $data) + { + $this->user->setConfig($data); + Notification::appendNotification(t('Configuration updated')); + } + + function ajaxSubmit($data) { + $config = $this->user->getConfig(); + if(isset($config)) + $data = array_merge($config, $data); + + $s = new moxl\StorageSet(); + $s->setXmlns('movim:prefs') + ->setData(serialize($data)) + ->request(); + } + + function ajaxGet() { + $s = new moxl\StorageGet(); + $s->setXmlns('movim:prefs') + ->request(); + } + + function build() + { + $languages = load_lang_array(); + /* We load the user configuration */ + $conf = $this->user->getConfig('language'); + $color = $this->user->getConfig('color'); + + $submit = $this->genCallAjax('ajaxSubmit', "movim_parse_form('general')") + . "this.className='button icon color orange loading'; setTimeout(function() {location.reload(false)}, 2000); this.onclick=null;"; + ?> +
    +
    +
    + +
    + +
    + +
    +
    +
    + +
    + +
    + + + + + + "> +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + +
    + + + +
    + + +

    +
    +

    +
    +
    +f}L*~a`L;Z PKCZl?^}@uHk--`OML81Y literal 0 HcmV?d00001 diff --git a/app/widgets/Config/color/cross.gif b/app/widgets/Config/color/cross.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ee9c7ac517bee40b78aea03afa809631f0b69fa GIT binary patch literal 83 zcmZ?wbhEHb + + jscolor demo + + + + + + Click here: + + + diff --git a/app/widgets/Config/color/hs.png b/app/widgets/Config/color/hs.png new file mode 100644 index 0000000000000000000000000000000000000000..3d94486cedaf7111d010fdaf2cefad45fd1f878b GIT binary patch literal 2684 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 YzFqsNg>|5V=vOIWZ|#VBZRvIQe;Bk#LI3~& literal 0 HcmV?d00001 diff --git a/app/widgets/Config/color/hv.png b/app/widgets/Config/color/hv.png new file mode 100644 index 0000000000000000000000000000000000000000..1c5e01f8bcecc4cf835e8eeeaa43ef2c06789022 GIT binary patch literal 2865 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 E0LKozl>h($ literal 0 HcmV?d00001 diff --git a/app/widgets/Config/color/jscolor.js b/app/widgets/Config/color/jscolor.js new file mode 100644 index 000000000..47cd4b1e2 --- /dev/null +++ b/app/widgets/Config/color/jscolor.js @@ -0,0 +1,953 @@ +/** + * jscolor, JavaScript Color Picker + * + * @version 1.4.0 + * @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html + * @author Jan Odvarko, http://odvarko.cz + * @created 2008-06-15 + * @updated 2012-07-06 + * @link http://jscolor.com + */ + + +var jscolor = { + + + dir : '', // location of jscolor directory (leave empty to autodetect) + bindClass : 'color', // class name + binding : true, // automatic binding via + preloading : true, // use image preloading? + + + install : function() { + jscolor.addEvent(window, 'load', jscolor.init); + }, + + + init : function() { + if(jscolor.binding) { + jscolor.bind(); + } + if(jscolor.preloading) { + jscolor.preload(); + } + }, + + + getDir : function() { + if(!jscolor.dir) { + var detected = jscolor.detectDir(); + jscolor.dir = detected!==false ? detected : 'jscolor/'; + } + return jscolor.dir; + }, + + + detectDir : function() { + var base = location.href; + + var e = document.getElementsByTagName('base'); + for(var i=0; i vs[a] ? + (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) : + tp[a], + -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ? + (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) : + (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c) + ]; + } + drawPicker(pp[a], pp[b]); + } + }; + + + this.importColor = function() { + if(!valueElement) { + this.exportColor(); + } else { + if(!this.adjust) { + if(!this.fromString(valueElement.value, leaveValue)) { + styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage; + styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor; + styleElement.style.color = styleElement.jscStyle.color; + this.exportColor(leaveValue | leaveStyle); + } + } else if(!this.required && /^\s*$/.test(valueElement.value)) { + valueElement.value = ''; + styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage; + styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor; + styleElement.style.color = styleElement.jscStyle.color; + this.exportColor(leaveValue | leaveStyle); + + } else if(this.fromString(valueElement.value)) { + // OK + } else { + this.exportColor(); + } + } + }; + + + this.exportColor = function(flags) { + if(!(flags & leaveValue) && valueElement) { + var value = this.toString(); + if(this.caps) { value = value.toUpperCase(); } + if(this.hash) { value = '#'+value; } + valueElement.value = value; + } + if(!(flags & leaveStyle) && styleElement) { + styleElement.style.backgroundImage = "none"; + styleElement.style.backgroundColor = + '#'+this.toString(); + styleElement.style.color = + 0.213 * this.rgb[0] + + 0.715 * this.rgb[1] + + 0.072 * this.rgb[2] + < 0.5 ? '#FFF' : '#000'; + } + if(!(flags & leavePad) && isPickerOwner()) { + redrawPad(); + } + if(!(flags & leaveSld) && isPickerOwner()) { + redrawSld(); + } + }; + + + this.fromHSV = function(h, s, v, flags) { // null = don't change + if(h !== null) { h = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, h)); } + if(s !== null) { s = Math.max(0.0, this.minS, Math.min(1.0, this.maxS, s)); } + if(v !== null) { v = Math.max(0.0, this.minV, Math.min(1.0, this.maxV, v)); } + + this.rgb = HSV_RGB( + h===null ? this.hsv[0] : (this.hsv[0]=h), + s===null ? this.hsv[1] : (this.hsv[1]=s), + v===null ? this.hsv[2] : (this.hsv[2]=v) + ); + + this.exportColor(flags); + }; + + + this.fromRGB = function(r, g, b, flags) { // null = don't change + if(r !== null) { r = Math.max(0.0, Math.min(1.0, r)); } + if(g !== null) { g = Math.max(0.0, Math.min(1.0, g)); } + if(b !== null) { b = Math.max(0.0, Math.min(1.0, b)); } + + var hsv = RGB_HSV( + r===null ? this.rgb[0] : r, + g===null ? this.rgb[1] : g, + b===null ? this.rgb[2] : b + ); + if(hsv[0] !== null) { + this.hsv[0] = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, hsv[0])); + } + if(hsv[2] !== 0) { + this.hsv[1] = hsv[1]===null ? null : Math.max(0.0, this.minS, Math.min(1.0, this.maxS, hsv[1])); + } + this.hsv[2] = hsv[2]===null ? null : Math.max(0.0, this.minV, Math.min(1.0, this.maxV, hsv[2])); + + // update RGB according to final HSV, as some values might be trimmed + var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]); + this.rgb[0] = rgb[0]; + this.rgb[1] = rgb[1]; + this.rgb[2] = rgb[2]; + + this.exportColor(flags); + }; + + + this.fromString = function(hex, flags) { + var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i); + if(!m) { + return false; + } else { + if(m[1].length === 6) { // 6-char notation + this.fromRGB( + parseInt(m[1].substr(0,2),16) / 255, + parseInt(m[1].substr(2,2),16) / 255, + parseInt(m[1].substr(4,2),16) / 255, + flags + ); + } else { // 3-char notation + this.fromRGB( + parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255, + parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255, + parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255, + flags + ); + } + return true; + } + }; + + + this.toString = function() { + return ( + (0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) + + (0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) + + (0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1) + ); + }; + + + function RGB_HSV(r, g, b) { + var n = Math.min(Math.min(r,g),b); + var v = Math.max(Math.max(r,g),b); + var m = v - n; + if(m === 0) { return [ null, 0, v ]; } + var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m); + return [ h===6?0:h, m/v, v ]; + } + + + function HSV_RGB(h, s, v) { + if(h === null) { return [ v, v, v ]; } + var i = Math.floor(h); + var f = i%2 ? h-i : 1-(h-i); + var m = v * (1 - s); + var n = v * (1 - s*f); + switch(i) { + case 6: + case 0: return [v,n,m]; + case 1: return [n,v,m]; + case 2: return [m,v,n]; + case 3: return [m,n,v]; + case 4: return [n,m,v]; + case 5: return [v,m,n]; + } + } + + + function removePicker() { + delete jscolor.picker.owner; + document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB); + } + + + function drawPicker(x, y) { + if(!jscolor.picker) { + jscolor.picker = { + box : document.createElement('div'), + boxB : document.createElement('div'), + pad : document.createElement('div'), + padB : document.createElement('div'), + padM : document.createElement('div'), + sld : document.createElement('div'), + sldB : document.createElement('div'), + sldM : document.createElement('div'), + btn : document.createElement('div'), + btnS : document.createElement('span'), + btnT : document.createTextNode(THIS.pickerCloseText) + }; + for(var i=0,segSize=4; i + * + * @version 1.0 + * @date 28 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class ConfigData extends WidgetBase +{ + function WidgetLoad() + { + $this->addcss('configdata.css'); + } + + function ajaxClearRosterLink() { + $rd = new \modl\RosterLinkDAO(); + $rd->clearRosterLink(); + + $this->refresh(); + } + + function ajaxClearMessage() { + $md = new \modl\MessageDAO(); + $md->clearMessage(); + + $this->refresh(); + } + + function ajaxClearPost() { + $pd = new \modl\PostnDAO(); + $pd->clearPost(); + + $this->refresh(); + } + + function refresh() { + $html = $this->prepareConfigData(); + RPC::call('movim_fill', 'configdata', $html); + RPC::commit(); + } + + function prepareConfigData() { + $cd = new \modl\ContactDAO(); + $stats = $cd->getStatistics(); + + $clearrosterlink = $this->genCallAjax('ajaxClearRosterLink'); + $clearmessage = $this->genCallAjax('ajaxClearMessage'); + $clearpost = $this->genCallAjax('ajaxClearPost'); + + $html = ' +
    +
    + '.t('Cache').' +
    +
    +
    + '.t('Clear').' +
    +
    +
    + '.t('Clear').' +
    +
    +
    + '.t('Clear').' +
    +
    +
    '; + return $html; + } + + function build() + { + ?> +
    + prepareConfigData(); ?> +
    + + * + * @version 1.0 + * @date 30 August 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class ContactCard extends WidgetCommon +{ + + function WidgetLoad() + { + $this->addcss('contactcard.css'); + $this->registerEvent('vcard', 'onVcard'); + } + + function onVcard($contact) + { + $html = $this->prepareContactCard($contact); + RPC::call('movim_fill', 'contactcard', $html); + } + + function prepareContactCard($contact) + { + $gender = getGender(); + $marital = getMarital(); + + $html .= ' +

    +

    '.t('Profile').'


    +
    + '.t('General Informations').''; + + if($this->testIsSet($contact->fn)) + $html .= '
    + + '.$contact->fn.' +
    '; + + if($this->testIsSet($contact->name)) + $html .= '
    + + '.$contact->name.' +
    '; + + if( + $contact->date != '0000-00-00' + && $contact->date != '1970-01-01' + && $this->testIsSet($contact->date)) + $html .= '
    + + '.date('j M Y',strtotime($contact->date)).' +
    '; + + if($contact->gender != 'N' && $this->testIsSet($contact->gender)) + $html .= '
    + + '.$gender[$contact->gender].' +
    '; + + if($contact->marital != 'none' && $this->testIsSet($contact->marital)) + $html .= '
    + + '.$marital[$contact->marital].' +
    '; + + if($this->testIsSet($contact->email)) + $html .= '
    + + '.$contact->email.' +
    '; + if($this->testIsSet($contact->url)) + $html .= '
    + + '.$contact->url.' +
    '; + + if($this->testIsSet($contact->desc) && prepareString($contact->desc) != '') + $html .= '
    + + '.prepareString($contact->desc).' +
    '; + + if($this->testIsSet($contact->adrlocality) || + $this->testIsSet($contact->adrcountry)) { + $html .= '
    +
    +
    + '.t('Geographic Position').''; + + if($this->testIsSet($contact->adrlocality)) { + $locality .= '
    + + '.$contact->adrlocality; + if($contact->adrpostalcode != 0) + $locality .= ' ('.$contact->adrpostalcode.')'; + $locality .= ' +
    '; + + $html .= $locality; + } + + if($this->testIsSet($contact->adrcountry)) + $html .= '
    + + '.$contact->adrcountry.' +
    '; + } + + $html .= '
    +
    jid."'").'">
    +
    '; + + return $html; + } + + function build() + { + $cd = new modl\ContactDAO(); + $contact = $cd->get($_GET['f']); + ?> +
    + prepareContactCard($contact); + ?> +
    + + * + * @version 1.0 + * @date 30 August 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class ContactInfo extends WidgetCommon +{ + function WidgetLoad() { + + } + + function ajaxRemoveContact($jid) { + $r = new moxl\RosterRemoveItem(); + $r->setTo($jid) + ->request(); + + $p = new moxl\PresenceUnsubscribe(); + $p->setTo($jid) + ->request(); + } + + + function prepareContactInfo() + { + $cd = new \modl\ContactDAO(); + $c = $cd->getRosterItem($_GET['f']); + + $html = ''; + + if(isset($c)) { + // Mood + if($c->mood) { + $moodarray = getMood(); + + $html .= '

    '.t('Mood').'

    '; + $mood = ''; + foreach(unserialize($c->mood) as $m) + $mood .= $moodarray[$m].','; + $html .= t("I'm ").substr($mood, 0, -1).'
    '; + } + + if($c->tuneartist || $c->tunetitle) { + $html .= '

    '.t('Listening').'

    '; + if($c->tuneartist) + $artist = $c->tuneartist. ' - '; + if($c->tunetitle) + $title = $c->tunetitle; + if($c->tunesource) + $album = t('on').' '.$c->tunesource; + $html .= $artist.$title.' '.$album; + } + + // Last seen + if($c->delay && $c->delay != '0000-00-00 00:00:00') { + $html .= '

    '.t('Last seen').'

    '; + $html .= prepareDate(strtotime($c->delay)).'
    '; + } + + if($c->loclatitude != '' && $c->loclongitude != '' + || $c->getPlace() != '') { + + $html .= ' +

    '.t('Location').'

    '; + + $html .= prepareDate(strtotime($c->loctimestamp)).'

    '; + if($c->getPlace() != '') + $html .= $c->getPlace().'

    '; + + if(isset($c->loclatitude) && isset($c->loclongitude)) + $html .= ' +
    + '; + + } + + + + + // Client informations + if($c->node && $c->ver) { + $node = $c->node.'#'.$c->ver; + + $cad = new \modl\CapsDAO(); + $caps = $cad->get($node); + + $clienttype = + array( + 'bot' => t('Bot'), + 'pc' => t('Desktop'), + 'phone' => t('Phone'), + 'handheld' => t('Phone'), + 'web' => t('Web'), + ); + + if(isset($caps) && $caps->name != '' && $caps->type != '' ) { + $cinfos = ''; + $cinfos .= $caps->name.' ('.$clienttype[$caps->type].')
    '; + + $html .='

    '.t('Client Informations').'

    ' . $cinfos; + } + } + + // Chat button + if($c->jid != $this->user->getLogin()) { + + $presences = getPresences(); + + $html .='

    '.t('Actions').'

    '; + + $ptoc = array( + 1 => 'green', + 2 => 'yellow', + 3 => 'red', + 4 => 'purple' + ); + + if(isset($c->presence) && !in_array($c->presence, array(5, 6))) { + $html .= ' + jid."'").'" + > + '.$presences[$c->presence].' - '.t('Chat').' + '; + } + } + + $html .= '
    '; + + $html .=' + + '.t('Remove this contact').' + + + + + '; + } elseif($_GET['f'] != $this->user->getLogin()) { + + $html .='

    '.t('Actions').'

    '; + + $html .=' + + '.t('Invite this user').' + '; + } + + return $html; + } + + function build() { + echo $this->prepareContactInfo(); + } +} diff --git a/app/widgets/ContactManage/ContactManage.php b/app/widgets/ContactManage/ContactManage.php new file mode 100644 index 000000000..0e2960f37 --- /dev/null +++ b/app/widgets/ContactManage/ContactManage.php @@ -0,0 +1,83 @@ + + * + * @version 1.0 + * @date 24 March 2013 + * + * Copyright (C)2013 MOVIM project + * + * See COPYING for licensing information. + */ + +class ContactManage extends WidgetCommon +{ + function WidgetLoad() { + + } + + public function ajaxContactManage($form) { + $rd = new \moxl\RosterUpdateItem(); + $rd->setTo(echapJid($form['jid'])) + ->setName(htmlspecialchars($form['alias'])) + ->setGroup(htmlspecialchars($form['group'])) + ->request(); + Notification::appendNotification(t('Contact updated')); + } + + private function prepareContactManage($jid) { + $rd = new \modl\RosterLinkDAO(); + + $groups = $rd->getGroups(); + $rl = $rd->get($jid); + + $submit = $this->genCallAjax('ajaxContactManage', "movim_parse_form('manage')"); + + $html = ''; + + $html .= '

    '.t('Manage').'

    '; + + $html .= ' +
    '; + + $ghtml = ''; + foreach($groups as $g) + $ghtml .= '
    '; + + return $html; + } + + function build() { + ?> +
    + user->getLogin()) + echo $this->prepareContactManage($_GET['f']); + } + +} diff --git a/app/widgets/ContactPubsubSubscription/ContactPubsubSubscription.php b/app/widgets/ContactPubsubSubscription/ContactPubsubSubscription.php new file mode 100644 index 000000000..cd8139ae2 --- /dev/null +++ b/app/widgets/ContactPubsubSubscription/ContactPubsubSubscription.php @@ -0,0 +1,75 @@ + + * + * @version 1.0 + * @date 24 March 2013 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class ContactPubsubSubscription extends WidgetBase +{ + + function WidgetLoad() + { + $this->registerEvent('groupsubscribedlist', 'onGroupSubscribedList'); + $this->registerEvent('groupsubscribedlisterror', 'onGroupSubscribedListError'); + } + + function prepareList($list) { + if(is_array($list[0])){ + $html = '
      '; + + foreach($list as $item){ + $html .= '
    • '.$item[2].'
    • '; + } + + $html .= '
    '; + return $html; + } + + Notification::appendNotification(t('No public groups found'), 'info'); + } + + function onGroupSubscribedList($list) { + $html = $this->prepareList($list); + RPC::call('movim_fill', 'publicgroups', $html); + } + + function onGroupSubscribedListError($error) + { + Notification::appendNotification($error, 'error'); + } + + function ajaxGetGroupSubscribedList($to){ + $r = new moxl\PubsubSubscriptionListGetFriends(); + $r->setTo($to)->request(); + } + + function build() + { + ?> + + diff --git a/app/widgets/ContactSummary/ContactSummary.php b/app/widgets/ContactSummary/ContactSummary.php new file mode 100644 index 000000000..b2897233a --- /dev/null +++ b/app/widgets/ContactSummary/ContactSummary.php @@ -0,0 +1,104 @@ + + * + * @version 1.0 + * @date 30 August 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class ContactSummary extends WidgetCommon +{ + + function WidgetLoad() + { + $this->addcss('contactsummary.css'); + $this->registerEvent('vcard', 'onVcard'); + } + + function onVcard($contact) + { + $html = $this->prepareContactSummary($contact); + RPC::call('movim_fill', 'contactsummary', $html); + } + + function ajaxRefreshVcard($jid) + { + $r = new moxl\VcardGet(); + $r->setTo($jid)->request(); + } + + function prepareContactSummary($contact) + { + $gender = getGender(); + $marital = getMarital(); + + // Contact avatar + $html .= ' + + '; + + $presencetxt = getPresencesTxt(); + + // Contact general infos + $html .= ' +

    '.$contact->getTrueName().'

    '; + + if($this->testIsSet($contact->name)) + $html .= $contact->name.' '; + else + $html .= $contact->getTrueName().' '; + + if($this->testIsSet($contact->url)) + $html .= '
    '.$contact->url.''; + + if($this->testIsSet($contact->status)) { + $html .= ' +
    + '.prepareString($contact->status).' +
    '; + } + + return $html; + } + + function build() + { + $cd = new modl\ContactDAO(); + + + if($_GET['f'] == $this->user->getLogin()) + $contact = $cd->get($this->user->getLogin()); + else + $contact = $cd->getRosterItem($_GET['f']); + + if(!isset($contact)) + $contact = $cd->get($_GET['f']); + ?> +
    + photobin)) { + echo $this->prepareContactSummary($contact); + } + + else { + $contact = new modl\Contact(); + echo $this->prepareContactSummary($contact); + ?> + + +
    + addcss('explore.css'); + } + + function ajaxSearchContacts($form) { + $html = $this->prepareContacts($form); + + RPC::call('movim_fill', 'contactsresult', $html); + RPC::commit(); + } + + function colorSearch($search, $text) { + return str_replace( + $search, + ''.$search.'', + $text + ); + } + + function prepareServers() { + $nd = new \modl\NodeDAO(); + + $servers = $nd->getServers(); + + $html = ''; + + return $html; + //var_dump($nd->getServers()); + } + + function prepareContacts($form = false) { + /*if(!$form){ + $where = array('public' => 1); + } + else{ + $where = array( + 'public' => 1, + array( + 'fn%' => '%'.$form['search'].'%', + '|jid%' => '%'.$form['search'].'%', + '|name%' => '%'.$form['search'].'%', + '|email%' => '%'.$form['search'].'%', + '|nickname%' => '%'.$form['search'].'%' + ) + ); + } + $users_limit = 20; + + $gender = getGender(); + $marital = getMarital(); + + $query = Contact::query()->select() + ->where($where) + //s->orderby('id', true) + ->limit(0, $users_limit); + $users = Contact::run_query($query); + + $html = ' +
    + + +
    +
    ';*/ + $cd = new \modl\ContactDAO(); + $users = array_reverse($cd->getAllPublic()); + + $gender = getGender(); + $marital = getMarital(); + + foreach($users as $user) { + $html .= ' +
    + + +
    + '. + $user->getTrueName().' + + '. + $user->getAge().' '. + $gender[$user->gender].' '. + $marital[$user->marital].' + +
    '.prepareString($user->desc).'
    +
    +
    +
    + '; + } + + return $html; + } + + function build() + { + ?> +
    + + +
    +

    + prepareServers(); ?> +
    + +
    +

    +
    +
    + prepareContacts(); ?> +
    +
    + addcss('feed.css'); + $this->addjs('feed.js'); + + $this->registerEvent('post', 'onStream'); + $this->registerEvent('postdeleted', 'onPostDelete'); + $this->registerEvent('postdeleteerror', 'onPostDeleteError'); + + $this->registerEvent('comment', 'onComment'); + $this->registerEvent('nocomment', 'onNoComment'); + $this->registerEvent('nocommentstream', 'onNoCommentStream'); + $this->registerEvent('commentpublisherror', 'onCommentPublishError'); + + $this->registerEvent('stream', 'onStream'); + $this->registerEvent('postpublished', 'onPostPublished'); + $this->registerEvent('postpublisherror', 'onPostPublishError'); + + $this->registerEvent('nodecreated', 'onNodeCreated'); + $this->registerEvent('nodecreationerror', 'onNodeCreationError'); + + $this->registerEvent('config', 'onConfig'); + + $this->cached = false; + } + + function onConfig(array $data) + { + $this->user->setConfig($data); + RPC::call('movim_fill', 'feedhead', $this->prepareHead()); + } + + function onNodeCreated() { + $config = $this->user->getConfig(); + $config['feed'] = 'created'; + + $s = new moxl\StorageSet(); + $s->setXmlns('movim:prefs') + ->setData(serialize($config)) + ->request(); + } + + function onNodeCreationError() { + $config = $this->user->getConfig(); + $config['feed'] = 'error'; + + $s = new moxl\StorageSet(); + $s->setXmlns('movim:prefs') + ->setData(serialize($config)) + ->request(); + + Notification::appendNotification( + t("Your server doesn't support post publication, you can only read contact's feeds"), + 'error'); + } + + function onCommentPublishError() { + $html = + '
    '. + t("Comment publication error").' +
    '; + RPC::call('movim_fill', 'feednotifs', $html); + } + + function onPostPublished($post) { + $pd = new \modl\PostnDAO(); + $pl = $pd->getFeed(-1, $this->_feedsize); + + $html = $this->preparePosts($pl); + + RPC::call('createCommentNode', $post->nodeid); + RPC::call('movim_fill', 'feedcontent', $html); + } + + function ajaxCreateCommentNode($parentid) { + $n = new moxl\MicroblogCommentCreateNode(); + $n->setTo($this->user->getLogin()) + ->setParentId($parentid) + ->request(); + } + + function onPostPublishError($error) { + Notification::appendNotification(t('An error occured : ').$error, 'error'); + } + + function prepareHead() { + $html = ''; + + global $session; + + if($session['config']['config'] == false) { + $html .= + '
    '. + t("Your server doesn't support post publication, you can only read contact's feeds"). + '
    '; + } elseif(!isset($session['config']['feed'])) { + $html .= ' +
    +
    '. + t("Creating your feed..."). + '
    +
    + '; + } else { + $html .= ' + + '.$this->prepareSubmitForm($this->user->getLogin(), 'urn:xmpp:microblog:0').' +
    '; + } + + return $html; + } + + function prepareFeed($start) { + $pd = new \modl\PostnDAO(); + $pl = $pd->getFeed($start+1, $this->_feedsize); + + + $html = $this->preparePosts($pl); + + // We ask for the HTML of all the posts + + $next = $start + $this->_feedsize; + + if(sizeof($pl) > $this->_feedsize-1 && $html != '') { + $html .= ' +
    +
    '. + t('Get older posts').' +
    +
    '; + } + + return $html; + } + + function ajaxGetFeed($start) { + $html = $this->prepareFeed($start); + RPC::call('movim_append', 'feedcontent', $html); + RPC::commit(); + } + + function onStream($payload) { + $html = ''; + $html = $this->prepareFeed(-1); + + if($html == '') + $html = ' +
    '. + t("Your feed cannot be loaded.").' +
    '; + RPC::call('movim_fill', 'feedcontent', $html); + + RPC::commit(); + } + + function ajaxCreateNode() + { + $p = new moxl\MicroblogCreateNode(); + $p->setTo($this->user->getLogin()) + ->request(); + } + + function build() + { + ?> +
    +
    + prepareHead(); + ?> +
    + + + +
    + prepareFeed(-1); + ?> +
    +
    + + * + * @version 1.0 + * @date 3 may 2012 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Help extends WidgetBase +{ + function WidgetLoad() { + } + + function build() + { + ?> +
    + +

    + +

    ', ''); ?>

    + +

    +
    +
    +
    +
    +
    +
    +
    + +

    + +

    +

      +
    • +
    • +
    • +
    • +
    • +
    +

    + +

    + +

    ', ''); ?> + + ', ''); ?>

    + +

    + +

    ', '', + 'movim@conference.movim.eu', + '', ''); ?>

    + +
    + + * + * @version 1.0 + * @date 20 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Log extends WidgetBase +{ + function widgetLoad() + { + $this->addcss('log.css'); + $this->registerEvent('allEvents', 'onEvent'); + } + + function build() + { + ?> +
    +

    + +
    +
    +
    + diff --git a/app/widgets/Log/log.css b/app/widgets/Log/log.css new file mode 100644 index 000000000..00f227a29 --- /dev/null +++ b/app/widgets/Log/log.css @@ -0,0 +1,29 @@ +/* Logs style */ + +#log { + background-color: rgba(0, 0, 0, 0.8); + color: white; +/* height: 350px;*/ + overflow: hidden; + font-size: 10px; + padding: 5px; + position: fixed; + bottom: 0; + left: 0; + width: 300px; + z-index: 3; + height: 12px; +} + +#log:hover { + position: fixed; + top: 0px; + right: 0px; + width: 40%; + height: 100%; + border-left: 1px solid black; +} + +#log span { + color: green; +} diff --git a/app/widgets/Login/Login.php b/app/widgets/Login/Login.php new file mode 100644 index 000000000..faed49b7e --- /dev/null +++ b/app/widgets/Login/Login.php @@ -0,0 +1,335 @@ + + * + * @version 1.0 + * @date 07 December 2011 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Login extends WidgetBase { + + function WidgetLoad() + { + $this->addcss('login.css'); + $this->addjs('login.js'); + $this->registerEvent('config', 'onConfig'); + } + + function onConfig(array $data) + { + $this->user->setConfig($data); + } + + private function displayWarning($warning, $htmlonly = false) + { + if($warning != false) { + switch ($warning) { + case 'noaccount': + $warning = ' +
    + '.t('Wrong username').' +
    '; + break; + case 'invalidjid': + $warning = ' +
    + '.t('Invalid JID').' +
    '; + break; + case 'errormechanism': + $warning = ' +
    + '.t('Authentication mechanism not supported by Movim').' +
    '; + break; + case 'errorchallenge': + $warning = ' +
    + '.t('Empty Challenge from the server').' +
    '; + break; + case 'dnsdomain': + $warning = ' +
    + '.t('XMPP Domain error, your account is not a correct Jabber ID').' +
    '; + break; + case 'datamissing': + $warning = ' +
    + '.t('Some data are missing !').' +
    '; + break; + case 'wrongpass': + $warning = ' +
    + '.t('Wrong password').' +
    '; + break; + case 'failauth': + $warning = ' +
    + '.t('The XMPP authentification failed').' +
    '; + break; + case 'bosherror': + $warning = ' +
    + '.t('The current BOSH URL in invalid').' +
    '; + break; + case 'internal': + $warning = ' +
    + '.t('Internal server error').' +
    '; + break; + case 'session': + $warning = ' +
    + '.t('Session error').' +
    '; + break; + case 'acccreated': + $warning = ' +
    + '.t('Account successfully created').' +
    '; + break; + case 'wrongaccount': + $warning = ' +
    + '.t('Movim failed to authenticate. You entered wrong data').' +
    '; + break; + case 'serverunauthorized': + $warning = ' +
    + '.t('Your XMPP server is unauthorized').' +
    '; + case 'mecerror': + $warning = ' +
    + '.t('The server takes too much time to repond').' +
    '; + break; + } + + if($htmlonly) + return $warning; + else { + RPC::call('movim_fill', 'warning', $warning); + RPC::call('loginButtonSet', t("Come in!")); + + RPC::commit(); + exit; + } + } + } + + function ajaxLogin($element) + { + // We get the Server Configuration + $serverconfig = Conf::getServerConf(); + + $warning = false; + + // Empty input test + foreach($element as $value) { + if($value == NULL || $value == '') { + $warning = 'datamissing'; + } + } + + $this->displayWarning($warning); + + // Correct email test + if(!filter_var($element['login'], FILTER_VALIDATE_EMAIL)) + $warning = 'invalidjid'; + + $this->displayWarning($warning); + + // Check whitelisted server + if( + $serverconfig['xmppWhiteList'] != '' &&! + in_array( + end( + explode('@', $element['login']) + ), + explode(',',$serverconfig['xmppWhiteList']) + ) + ) + $warning = 'serverunauthorized'; + $this->displayWarning($warning); + + // Correct XMPP account test + $login_arr = explode('@', $element['login']); + $user = $login_arr[0]; + $host = $login_arr[1]; + + $dns = dns_get_record('_xmpp-client._tcp.'.$login_arr[1]); + + if(isset($dns[0]['target']) && $dns[0]['target'] != null) + $domain = $dns[0]['target']; + else { + $domain = $host; + //$warning = 'dnsdomain'; + } + + $this->displayWarning($warning); + + global $session; + + if($s != false) { + $session = $sess->get('session'); + } + else { + $session = array( + 'rid' => 1, + 'sid' => 0, + 'id' => 0, + 'url' => $serverconfig['boshUrl'], + 'port'=> 5222, + 'host'=> $host, + 'domain' => $domain, + 'ressource' => 'moxl'.substr(md5(date('c')), 3, 6), + + 'user' => $user, + 'password' => $element['pass'], + + 'proxyenabled' => $serverconfig['proxyEnabled'], + 'proxyurl' => $serverconfig['proxyURL'], + 'proxyport' => $serverconfig['proxyPort'], + 'proxyuser' => $serverconfig['proxyUser'], + 'proxypass' => $serverconfig['proxyPass']); + } + + $sess = Session::start(APP_NAME); + + $sess->set('session', $session); + + // BOSH + XMPP connexion test + $warning = moxl\login(); + if($warning != 'OK') + $this->displayWarning($warning); + + $pd = new modl\PresenceDAO(); + $pd->clearPresence($element['login']); + + RPC::call('enterMovim', Route::urlize('main')); + RPC::commit(); + } + + function ajaxGetConfig() + { + $s = new moxl\StorageGet(); + $s->setXmlns('movim:prefs') + ->request(); $evt = new \Event(); + $evt->runEvent('nostream'); + } + + function build() + { + $submit = $this->genCallAjax('ajaxLogin', "movim_parse_form('login')"); + + ?> +
    + + '.t('Your web browser is too old to use with Movim.').' +
    '; + } else { + ?> + +
    +
    + "/> +
    +
    + "/> +
    +
    + +
    + + + +
    + +
      +
    • + + + +
    • +
    • + ', '')?> +
    • +
    • + ', ''); ?> +
    • +
    + + + +
    displayWarning($_GET['err'], true); ?>
    +
    + + + + + +
    +
    + +
    + + + +
    + + + +
    + + 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 B_v8Qo literal 0 HcmV?d00001 diff --git a/app/widgets/Login/img/logo.svg b/app/widgets/Login/img/logo.svg new file mode 100644 index 000000000..5e19e3532 --- /dev/null +++ b/app/widgets/Login/img/logo.svg @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/widgets/Login/img/logo2.svg b/app/widgets/Login/img/logo2.svg new file mode 100644 index 000000000..2c39c7b23 --- /dev/null +++ b/app/widgets/Login/img/logo2.svg @@ -0,0 +1,238 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/widgets/Login/login.css b/app/widgets/Login/login.css new file mode 100644 index 000000000..6c78f57a8 --- /dev/null +++ b/app/widgets/Login/login.css @@ -0,0 +1,155 @@ +body { + width: 100%; + margin: 0 auto; + max-width: 28em; +} + +#content { + margin: 0 auto; + width: 100%; +} + +#loginpage { + display: block; + margin: 0 auto; + height: 100%; + + background-image: url(img/logo.png); + background-repeat: no-repeat; + background-position: center 1em; + background-size: auto auto; + padding-top: 40%; + + margin-top: 40%; +} + +#loginpage .admin { + position: fixed; + bottom: 0px; + right: 0px; + color: white; + padding: 1em; +} + +#loginpage .admin a:link, +#loginpage .admin a:visited { + color: white; +} + +#loginpage #warning { + margin-bottom: 0.7em; +} + +#loginpage #connectform { + padding: 0.6em; + background-color: rgba(255, 255, 255, 0.2); + /*border: 1px solid rgba(255, 255, 255, 0.1); + border-top: 1px solid rgba(255, 255, 255, 0.4); + border-radius: 4px; + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2);*/ + border-radius: 0.1em; +} + +#loginpage #connectform .element { + display: block; + margin: 0 auto; + padding: 0px; + width: 100%; + min-height: 2.5em; +} + +#loginpage #connectform .element:last-child { + min-height: 1em; +} + +#loginpage #connectform .element input { + margin: 0px; + border: 0px; + /*border-color: rgba(0, 0, 0, 0.3) rgba(0, 0, 0, 0.2) rgba(200, 200, 200, 0.3);*/ + box-shadow: none; + color: black; + background-color: rgba(255, 255, 255, 0.3); +} + +#loginpage #connectform a[name=submit] { + display: block; + text-align: center; + /*margin: 0px 1px; + display: block; + text-align: center; + margin-top: 1px; + + border-radius: 1px; + + box-shadow: 1px 0px 0px rgba(0, 0, 0, 0.3), + -1px 0px 0px rgba(0, 0, 0, 0.3), + 0px 1px 0px rgba(0, 0, 0, 0.4), + 0px -1px 0px rgba(0, 0, 0, 0.4); + + border: 0px; + border: 1px solid rgba(255, 255, 255, 0.4); + border-top: 1px solid rgba(255, 255, 255, 0.6); + border-bottom: 1px solid rgba(255, 255, 255, 0.4); + + background: linear-gradient(top, + rgba(255, 255, 255, 0.2) 0px, + rgba(255, 255, 255, 0.2) 2px, + rgba(255, 255, 255, 0.05) 100%); + background: -moz-linear-gradient(top, + rgba(255, 255, 255, 0.2) 0px, + rgba(255, 255, 255, 0.2) 2px, + rgba(255, 255, 255, 0.05) 100%); + background: -webkit-linear-gradient(top, + rgba(255, 255, 255, 0.2) 0px, + rgba(255, 255, 255, 0.2) 2px, + rgba(255, 255, 255, 0.05) 100%); + background: -o-linear-gradient(top, + rgba(255, 255, 255, 0.2) 0px, + rgba(255, 255, 255, 0.2) 2px, + rgba(255, 255, 255, 0.05) 100%); + + background-color: #76AB16; + text-shadow: -1px -1px 0px rgba(0, 0, 0, 0.4); + + color: white;*/ +} + +#connectform a[name=submit]:before { + color: white; +} + +#loginpage .infos { + color: white; + text-align: center; +} + +#loginpage #loginhelp { + list-style-type: none; + color: white; + line-height: 1.2em; + text-align: justify; + transition: height 1s ease; + height: 0em; + overflow: hidden; +} + +#loginpage #loginhelp li { + height: 2.5em; + background-repeat: no-repeat; + background-image: url(img/beaker.png); + padding-left: 2.5em; + background-position: 0.2em center; + margin: 0.5em 0em; +} + +#loginpage #connectform:hover > #loginhelp { + height: 9em; +} + +#loginpage #loginhelp li#jabber { background-image: url(img/jabber.png); } +#loginpage #loginhelp li#gmail { background-image: url(img/envelope.png); } +#loginpage #loginhelp li#facebook { background-image: url(img/facebook.png); } + +#footer { + display: none; +} diff --git a/app/widgets/Login/login.js b/app/widgets/Login/login.js new file mode 100644 index 000000000..6b5944028 --- /dev/null +++ b/app/widgets/Login/login.js @@ -0,0 +1,12 @@ +function enterMovim(url) { + window.location.href = url; +} + +function loginButtonSet(val, loading) { + document.querySelector('#submit').innerHTML = val; +} + +function fillExample(login, pass) { + document.querySelector('#login').value = login; + document.querySelector('#pass').value = pass; +} diff --git a/app/widgets/Logout/Logout.php b/app/widgets/Logout/Logout.php new file mode 100644 index 000000000..9c2f7a493 --- /dev/null +++ b/app/widgets/Logout/Logout.php @@ -0,0 +1,125 @@ + + * + * @version 1.0 + * @date 20 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Logout extends WidgetBase +{ + + function WidgetLoad() + { + $this->addcss('logout.css'); + $this->addjs('logout.js'); + $this->registerEvent('mypresence', 'onMyPresence'); + } + + function onMyPresence() + { + $html = $this->preparePresence(); + RPC::call('movim_fill', 'logout', $html); + RPC::commit(); + } + + function onPostDisconnect($data) + { + RPC::call('movim_reload', + BASE_URI."index.php?q=disconnect"); + } + + function ajaxLogout() + { + $presence = Cache::c('presence'); + Cache::c( + 'presence', + array( + 'status' => $presence['status'], + 'show' => $presence['show'] + ) + ); + $this->xmpp->logout(); + } + + function ajaxSetStatus($show) + { + // We update the cache with our status and presence + $presence = Cache::c('presence'); + + if($show == "boot") $show = $presence['show']; + Cache::c( + 'presence', + array( + 'status' => $presence['status'], + 'show' => $show + ) + ); + + switch($show) { + case 'chat': + $p = new moxl\PresenceChat(); + $p->setStatus($presence['status'])->request(); + break; + case 'away': + $p = new moxl\PresenceAway(); + $p->setStatus($presence['status'])->request(); + break; + case 'dnd': + $p = new moxl\PresenceDND(); + $p->setStatus($presence['status'])->request(); + break; + case 'xa': + $p = new moxl\PresenceXA(); + $p->setStatus($presence['status'])->request(); + break; + } + } + + function preparePresence() + { + $txt = getPresences(); + $txts = getPresencesTxt(); + + global $session; + + $pd = new \modl\PresenceDAO(); + $p = $pd->getPresence($this->user->getLogin(), $session['ressource']); + + $html = '
    '.$txt[$p->presence].'
    '; + + $html .= ' + + '; + + return $html; + } + + function build() + { + ?> +
    + preparePresence(); ?> +
    + diff --git a/app/widgets/Logout/img/away.png b/app/widgets/Logout/img/away.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd38e3d3fd70a7614c7b9f0066809e990bf2329 GIT binary patch literal 436 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4u@pObhHwBu4M$1`kk47*5n0T@ zz_<~F853t{@BsxSOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kpikV^mK6y zk(g>b!8R{AQNZ>6ADhP>OHRnWkWu-yq|CYbMw|HrkxrIQ5seogf`X3TWOO<7iR*2H=dop|J%J^ z6=#6zXCAI)33U!_QrIFIa@GA>npPL5i-J;s>5S5Vzz&WwnSjSf9EDVF>@fcOHaS~C z+Cyp9h3=Tp)!{*mO#&1D_paq~=K8f^YF^d+bhi{Xqqe(64rvRtKKwqJ{97mfE6{Zj z`MXYcC>pc7@O0c*)PLmfVU272caQEqU%vg*`wz4E^Ox!GGBbXx;(eoiom}f4u@pObhHwBu4M$1`kk47*5n0T@ zz_<~F853t{@BsxSOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kpimb_H=O! zk(g?G!O$xr)q3QARfXV`txn ze@OlR?O#a$Z~1G^7hQQ)t!ffjax(3X&$*lP@AJExKI!!e30+v;$h4<{N5{=kbSLKp zE=D1)4#f#AEF2Cln^rX#COmdsQvBL`!$C7yYmfeS(ZT0D{dRu+nwxec`-sH)smA5z z=8r8;zP!Ic_1&|jQ_OgON$s|m-}jf#?)jX*^_hOp_|9+LX74;lF8*%a_1h1x%ky7* qvWYQF*2cXj_{h(T{jgeF?hQAxvXf4u@pObhHwBu4M$1`kk47*5n0T@ zz_<~F853t{@BsxSOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kpik_@pN$v zk(lZ`!PcueP{if@o$sDHEaHc>*o}0k5Va27oFU||M zHQp69HOMk*aDF?X>+5;#otcwn%QKW(#AM4^tMC4}iPJ~okFuHfd1ZZ*&PQ`H7QEtb zJFsTI((}}v-G$|5vGqn?M`xdkzRf4u@pObhHwBu4M$1`kk47*5n0T@ zz_<~F853t{@BsxSOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kpimL^>lFz zk(lax!LU!sP{8fs{x_Sfow6>5-{>*+Ii<;Q!t$`shTZNFO}rD_T2h`UfAa0b(hTXkNG_lcdv8iV02+&Sh4ljoX@9Umi#)dxwQBD zJfLuo;966LhE+{71HB$*&NA~06+dTL@m?^Q#rUx0_mKUIShrtWv$ZWsyXaiTTF20f zQPr=~(tKRR1%Eoa2nf!QbYW3yiqh`jP;BX*eKzfO)aoa5CI&fqaayL^$ni5U7<=FU zUjOH3&A)mZxtC?T_f83#)3IO*69b3h2?L(}-+uqKu9dgzd+Zh}&d@VczxKX;dp(or Xi`|#+M~KG(LzltR)z4*}Q$iB}!{M#o literal 0 HcmV?d00001 diff --git a/app/widgets/Logout/logout.css b/app/widgets/Logout/logout.css new file mode 100644 index 000000000..e830f3bf1 --- /dev/null +++ b/app/widgets/Logout/logout.css @@ -0,0 +1,60 @@ +#logout { + font-size: 1em; + color: #ccc; +} + +#logout .online { background-image: url(img/online.png); } +#logout .away { background-image: url(img/away.png); } +#logout .dnd { background-image: url(img/dnd.png); } +#logout .xa { background-image: url(img/xa.png); } + +#logouttab { + position: fixed; + top: 0px; + right: 50%; + margin-right: -250px; + cursor: pointer; + z-index: 5; + line-height: 3em; + padding-left: 3em; + padding-right: 1em; + background-repeat: no-repeat; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background-position: 1em center; + color: white; +} + +#logouttab:hover { + background-color: #46565E; +} + +#logoutlist { + display: none; + position: fixed; + top: 3em; + right: 50%; + margin-right: -300px; + z-index: 1; + background-color: #4C5A61; + overflow: hidden; + width: 200px; +} + +#logoutlist a { + display: block; + line-height: 3em; + background-repeat: no-repeat; + background-position: 0.5em center; + padding-left: 2em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: white; +} + +#logoutlist a:hover { + cursor: pointer; + background-color: #46565E; +} diff --git a/app/widgets/Logout/logout.js b/app/widgets/Logout/logout.js new file mode 100644 index 000000000..697163046 --- /dev/null +++ b/app/widgets/Logout/logout.js @@ -0,0 +1,9 @@ +function showLogoutList() { + hideNotifsList(); + + movim_toggle_display('#logoutlist'); +} + +function hideLogoutList() { + document.getElementById('logoutlist').style.display = 'none'; +} diff --git a/app/widgets/Media/Media.php b/app/widgets/Media/Media.php new file mode 100644 index 000000000..b392bdf7c --- /dev/null +++ b/app/widgets/Media/Media.php @@ -0,0 +1,158 @@ + + * + * @version 1.0 + * @date 07 December 2011 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Media extends WidgetBase { + function WidgetLoad() + { + $this->addcss('media.css'); + $this->addjs('media.js'); + + if(!is_dir($this->user->userdir)) { + mkdir($this->user->userdir); + touch($this->user->userdir.'index.html'); + } + + $this->registerEvent('media', 'onMediaUploaded'); + } + + function ajaxRefreshMedia() + { + $html = $this->mainFolder(); + RPC::call('movim_fill', 'media', $html); + RPC::commit(); + } + + function ajaxDeleteItem($name) + { + unlink($this->user->userdir.'thumb_'.$name); + unlink($this->user->userdir.'medium_'.$name); + unlink($this->user->userdir.$name); + + $this->ajaxRefreshMedia(); + } + + function listFiles() + { + $html = '
      '; + + foreach(scandir($this->user->userdir) as $s) { + if( + $s != '.' && + $s != '..' && + substr($s, 0, 6) != 'thumb_' && + substr($s, 0, 7) != 'medium_' && + $s != 'index.html') + $html .= + '
    • + + +
      x
      +
    • + '; + } + + $html .= '
    '; + + return $html; + } + + function mainFolder() + { + $percent = number_format(($this->user->dirSize()/$this->user->sizelimit)*100, 2); + + $html = + $this->listFiles().' + + '.sizeToCleanSize($this->user->dirSize()).' '.t('on').' '.sizeToCleanSize($this->user->sizelimit). + ' - '. + $percent.'% + '; + + return $html; + } + + function pictureViewer($f) + { + if(file_exists($this->user->userdir.$f) && getimagesize($this->user->userdir.$f) != 0) { + + $er = @exif_read_data($this->user->userdir.$f); + + + $exif = ''; + + if($er) { + if(isset($er['FileName'])) + $exif .= '
  • '.t('Name').''.$er['FileName'].'
  • '; + if(isset($er['COMPUTED']['Width']) && isset($er['COMPUTED']['Height'])) + $exif .= '
  • '.t('Resolution').''.$er['COMPUTED']['Width'].'x'.$er['COMPUTED']['Height'].'
  • '; + if(isset($er['FileSize'])) + $exif .= '
  • '.t('Size').''.sizeToCleanSize($er['FileSize']).'
  • '; + if(isset($er['DateTime'])) + $exif .= '
  • '.t('Date').''.prepareDate(strtotime($er['DateTime'])).'
  • '; + if(isset($er['ISOSpeedRatings'])) + $exif .= '
  • '.t('ISO').''.$er['ISOSpeedRatings'].'
  • '; + if(isset($er['Model'])) + $exif .= '
  • '.t('Camera').''.$er['Model'].'
  • '; + if(isset($er['Artist'])) + $exif .= '
  • '.t('Artist').''.$er['Artist'].'
  • '; + } + + $exif .= '
  • '.t('Original').''.t('Link').'
  • '; + + $html = ' +
    + + +
    +
      + '.$exif.' +
    +
    +
    '; + + return $html; + } + } + + function build() + { + $refresh = $this->genCallAjax('ajaxRefreshMedia'); + ?> + + +
    + pictureViewer($_GET['f']); ?> +
    + +
    + mainFolder(); ?> +
    + 8n!${HiL7I2LAID7Mu?KB5XRaVGnQejjU}O< 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Π=_i=DVy)qPD6Ybl6@|uOpl`e`_lJ?aS|N5Ad;I< z-v};It7}sn2rW?wQa%+xE@d2f&3j}4IdrmQybi7=!nndk3B_IvbD`EWu>9LdJlEhc z1Kz|y2&eONsz7(WZ`thx8}GD7fXq!N(N&%|lRC04{|PTregfagoN4;)7Ao=vieMJo z$XyO?o%wqhybdwa2}aj9WXB`a@WaVzlli;>RF%bbVj7n6ZMO1IAq8QZqr@aFrO)RF-FZBiBNHG+9549wq8LnrgH&&5C$J*zTIg=VIux|L z{mimk5MXMhh3bP=LA$$9AaU;t?nmKSYf%u1^iu(qV|PgD=lqZvoH+qdfR2xvMrgMN zH2q1`sK_R}gEsv|JH9q~s742TU)YoLiTE+(&PT&n5f=y zU|ZdjDHT+>8c;COCiA@bInAs34le~d;@N?)C+*BFMjj0{*&0r8NybgiTFXvMY9h%5 zw+)`h_EB<%HEsuK{0QDUoo&_j)dEkBcC$`nGbDaeP4kMGz`b3vVdZ59f4>(M)rRQ6 zLDFr7Tg#YHzP83`Xv&>X#LX?AG-@q3G$n2-(r6Rc2YLkHP{j6Zmdhk1QtEW73a`tV z74&>;S-T-+1FkslNmULpWzXnlR{W&YE)f2X`pdA-k9e!JY=~L2% z@xEYEa720PsHChUy&7rrj)v2 zBjMN!X@TNbt*Qy-ZCCci+G)C>10!57P$ZR2G~5>2ri6bGHucqMN(0hG;qz|i4bOpO zPB_`~7-5jixDhSO9Lo{pAuM)|6V+z^Wn|$@WWXU{Lix$Z`B*Eh=1k8u^g8Qs9&ppd K+PK2VBkq5u#s(<> literal 0 HcmV?d00001 diff --git a/app/widgets/Media/media.css b/app/widgets/Media/media.css new file mode 100644 index 000000000..2b83dabf7 --- /dev/null +++ b/app/widgets/Media/media.css @@ -0,0 +1,115 @@ +#main { + +} + +#center { + position: relative; +} + +#navtabs, #navtabs li.on { + background-color: transparent; + color: white; +} + +#navtabs li.on { + background-color: #111; +} + +#media .breadcrumb { + background-color: transparent; +} + +#media .breadcrumb a:after { + border-color: #222; +} + +#media ul.thumb a { + position: relative; +} + +#media ul.thumb li div.remove { + position: absolute; + bottom: 0px; + right: 0px; + background-color: rgba(0, 0, 0, 0.6); + border-radius: 3px 0px 0px 0px; + font-weight: bold; + width: 26px; + height: 26px; + text-align: center; + line-height: 26px; + font-size: 16px; + display: none; +} + +#media ul.thumb li:hover div.remove { + display: block; +} + +#media ul.thumb li:hover div.remove:hover { + background-color: black; + cursor: pointer; +} + +#media a:link, #media a:visited, +#viewer a:link, #viewer a:visited { + color: #DDD; +} + +#navtabs li:hover { + background-color: #111; +} + +#center { + background-color: #222; + color: white; +} + +#viewer .viewer { + position: relative; +} + +#viewer .viewer img { + width: 100%; + height: auto; + display: block; +} + +#viewer .viewer .exif { + position: absolute; + bottom: 0px; + background-color: rgba(0, 0, 0, 0.8); + width: 100%; + padding: 1em; +} + +#viewer .viewer .exif ul { + list-style-type: none; +} + +#viewer .viewer .exif ul li { + width: 50%; + display: block; + float: left; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +#viewer .viewer .exif span { + font-weight: bold; + display: inline-block; + text-align: right; + margin-right: 1em; + width: 5em; +} + +#media .size { + position: absolute; + font-size: 0.9em; + top: 0px; + right: 0px; + line-height: 3em; + display: block; + padding-right: 1em; +} diff --git a/app/widgets/Media/media.js b/app/widgets/Media/media.js new file mode 100644 index 000000000..9d53776c1 --- /dev/null +++ b/app/widgets/Media/media.js @@ -0,0 +1,181 @@ +// common variables +var iBytesUploaded = 0; +var iBytesTotal = 0; +var iPreviousBytesLoaded = 0; +var iMaxFilesize = 1048576; // 1MB +var oTimer = 0; +var sResultFileSize = ''; + +function secondsToTime(secs) { // we will use this function to convert seconds in normal time format + var hr = Math.floor(secs / 3600); + var min = Math.floor((secs - (hr * 3600))/60); + var sec = Math.floor(secs - (hr * 3600) - (min * 60)); + + if (hr < 10) {hr = "0" + hr; } + if (min < 10) {min = "0" + min;} + if (sec < 10) {sec = "0" + sec;} + if (hr) {hr = "00";} + return hr + ':' + min + ':' + sec; +}; + +function bytesToSize(bytes) { + var sizes = ['Bytes', 'KB', 'MB']; + if (bytes == 0) return 'n/a'; + var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); + return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]; +}; + +function fileSelected() { + + // hide different warnings + document.getElementById('upload_response').style.display = 'none'; + document.getElementById('error').style.display = 'none'; + document.getElementById('error2').style.display = 'none'; + document.getElementById('abort').style.display = 'none'; + document.getElementById('warnsize').style.display = 'none'; + + // get selected file element + var oFile = document.getElementById('image_file').files[0]; + + document.getElementById('uploadbutton').style.display = 'inline-block'; + + var img = new Image; + img.onerror = function() { + document.getElementById('error').style.display = 'block'; + document.getElementById('uploadbutton').style.display = 'none'; + return; + }; + + // little test for filesize + if (oFile.size > iMaxFilesize) { + document.getElementById('warnsize').style.display = 'block'; + document.getElementById('uploadbutton').style.display = 'none'; + return; + } + + // get preview element + var oImage = document.getElementById('preview'); + + // prepare HTML5 FileReader + var oReader = new FileReader(); + oReader.onload = function(e){ + + img.src = e.target.result; + + // e.target.result contains the DataURL which we will use as a source of the image + oImage.src = e.target.result; + + oImage.onload = function () { // binding onload event + + // we are going to display some custom image information here + sResultFileSize = bytesToSize(oFile.size); + document.getElementById('fileinfo').style.display = 'block'; + document.getElementById('filename').innerHTML = 'Name: ' + oFile.name; + document.getElementById('filesize').innerHTML = 'Size: ' + sResultFileSize; + document.getElementById('filetype').innerHTML = 'Type: ' + oFile.type; + document.getElementById('filedim').innerHTML = 'Dimension: ' + oImage.naturalWidth + ' x ' + oImage.naturalHeight; + }; + }; + + // read selected file as DataURL + oReader.readAsDataURL(oFile); +} + +function startUploading() { + // cleanup all temp states + iPreviousBytesLoaded = 0; + document.getElementById('upload_response').style.display = 'none'; + document.getElementById('error').style.display = 'none'; + document.getElementById('error2').style.display = 'none'; + document.getElementById('abort').style.display = 'none'; + document.getElementById('warnsize').style.display = 'none'; + document.getElementById('progress_percent').innerHTML = ''; + var oProgress = document.getElementById('progress'); + oProgress.style.display = 'block'; + oProgress.style.width = '0px'; + + // get form data for POSTing + var vFD = new FormData(document.getElementById('upload_form')); + + // create XMLHttpRequest object, adding few event listeners, and POSTing our data + var oXHR = new XMLHttpRequest(); + oXHR.upload.addEventListener('progress', uploadProgress, false); + oXHR.addEventListener('load', uploadFinish, false); + oXHR.addEventListener('error', uploadError, false); + oXHR.addEventListener('abort', uploadAbort, false); + oXHR.open('POST', 'upload.php'); + oXHR.send(vFD); + + // set inner timer + oTimer = setInterval(doInnerUpdates, 300); +} + +function doInnerUpdates() { // we will use this function to display upload speed + var iCB = iBytesUploaded; + var iDiff = iCB - iPreviousBytesLoaded; + + // if nothing new loaded - exit + if (iDiff == 0) + return; + + iPreviousBytesLoaded = iCB; + iDiff = iDiff * 2; + var iBytesRem = iBytesTotal - iPreviousBytesLoaded; + var secondsRemaining = iBytesRem / iDiff; + + // update speed info + var iSpeed = iDiff.toString() + 'B/s'; + if (iDiff > 1024 * 1024) { + iSpeed = (Math.round(iDiff * 100/(1024*1024))/100).toString() + 'MB/s'; + } else if (iDiff > 1024) { + iSpeed = (Math.round(iDiff * 100/1024)/100).toString() + 'KB/s'; + } + + document.getElementById('speed').innerHTML = iSpeed; + document.getElementById('remaining').innerHTML = ' ' + secondsToTime(secondsRemaining); +} + +function uploadProgress(e) { // upload process in progress + if (e.lengthComputable) { + iBytesUploaded = e.loaded; + iBytesTotal = e.total; + var iPercentComplete = Math.round(e.loaded * 100 / e.total); + var iBytesTransfered = bytesToSize(iBytesUploaded); + + document.getElementById('progress_percent').innerHTML = iPercentComplete.toString() + '%'; + document.getElementById('progress').style.width = (iPercentComplete * 4).toString() + 'px'; + document.getElementById('b_transfered').innerHTML = iBytesTransfered; + if (iPercentComplete == 100) { + var oUploadResponse = document.getElementById('upload_response'); + oUploadResponse.innerHTML = '

    Please wait...processing

    '; + oUploadResponse.style.display = 'block'; + } + } else { + document.getElementById('progress').innerHTML = 'unable to compute'; + } +} + +function uploadFinish(e) { // upload successfully finished + var oUploadResponse = document.getElementById('upload_response'); + oUploadResponse.innerHTML = e.target.responseText; + oUploadResponse.style.display = 'block'; + + document.getElementById('progress_percent').innerHTML = '100%'; + document.getElementById('progress').style.width = '400px'; + document.getElementById('filesize').innerHTML = sResultFileSize; + document.getElementById('remaining').innerHTML = ' 00:00:00'; + + clearInterval(oTimer); + + refreshMedia(); +} + +function uploadError(e) { // upload error + document.getElementById('error2').style.display = 'block'; + clearInterval(oTimer); +} + +function uploadAbort(e) { // upload abort + document.getElementById('abort').style.display = 'block'; + clearInterval(oTimer); +} diff --git a/app/widgets/MediaUpload/MediaUpload.php b/app/widgets/MediaUpload/MediaUpload.php new file mode 100644 index 000000000..196bb79ec --- /dev/null +++ b/app/widgets/MediaUpload/MediaUpload.php @@ -0,0 +1,86 @@ + + * + * @version 1.0 + * @date 07 December 2011 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class MediaUpload extends WidgetBase { + function WidgetLoad() + { + $this->addcss('mediaupload.css'); + } + + function build() + { + if($this->user->dirSize() < $this->user->sizelimit) { + ?> +
    +
    +
    +
    + + +
    + + + +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    + + +
    + +
    +
    + +
    +
    + +
    +
    + +
    + +
    +
    + + * + * @version 1.0 + * @date 20 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Node extends WidgetCommon +{ + function WidgetLoad() + { + $this->registerEvent('stream', 'onStream'); + $this->registerEvent('nostream', 'onStream'); + $this->registerEvent('pubsubsubscribed', 'onPubsubSubscribed'); + $this->registerEvent('pubsubsubscribederror', 'onPubsubSubscribedError'); + $this->registerEvent('pubsubunsubscribed', 'onPubsubUnsubscribed'); + } + + function onPubsubSubscribed($params) + { + $html = $this->prepareGroup($params[0], $params[1]); + RPC::call('setBookmark'); + RPC::call('movim_fill', 'node', $html); + RPC::call('movim_reload_this'); + } + + function onPubsubSubscribedError($params) + { + $this->onPubsubSubscribed($params); + } + + function onPubsubUnsubscribed($params) + { + $this->onPubsubSubscribed($params); + } + + function onStream($payload) { + $html = $this->prepareGroup($payload['from'], $payload['node']); + + if($html == '') + $html = t("Your feed cannot be loaded."); + RPC::call('movim_fill', md5($payload['from'].$payload['node']), $html); + } + + function ajaxGetItems($server, $node) + { + $r = new moxl\PubsubGetItems(); + $r->setTo($server) + ->setNode($node) + ->request(); + } + + function ajaxSubscribe($data, $server, $node) + { + $g = new moxl\PusubSubscribe(); + $g->setTo($server) + ->setNode($node) + ->setFrom($this->user->getLogin()) + ->setData($data) + ->request(); + } + + function ajaxUnsubscribe($server, $node) + { + $sd = new \modl\SubscriptionDAO(); + + foreach($sd->get($server, $node) as $s) { + $g = new moxl\PubsubUnsubscribe(); + $g->setTo($server) + ->setNode($node) + ->setSubid($s->subid) + ->setFrom($this->user->getLogin()) + ->request(); + } + } + + function ajaxGetSubscriptions($server, $node) + { + $r = new moxl\PubsubGetSubscriptions(); + $r->setTo($server) + ->setNode($node) + ->request(); + } + + function prepareGroup($serverid, $groupid) { + if($this->searchSubscription($serverid, $groupid)) + $button = ' + + '.t('Unsubscribe').' + '; + else + $button = ' + '; + + $html = ' + + + + + '; + + $title = ''; + + $pd = new modl\PostnDAO(); + $posts = $pd->getNode($serverid, $groupid, 0, 10); + + $html .= $title; + + if($this->searchSubscription($serverid, $groupid)) + $html .= $this->prepareSubmitForm($serverid, $groupid); + + $html .= $this->preparePosts($posts); + + return $html; + } + + function searchSubscribed($server, $node) { + $c = Cache::c('bookmark'); + foreach($c as $bookmark) { + if( + $bookmark['type'] == 'subscription' && + $bookmark['server'] == $server && + $bookmark['node'] == $node) { + return true; + } + } + return false; + } + + function searchSubscription($server, $node) { + $sd = new \modl\SubscriptionDAO(); + + foreach($sd->get($server, $node) as $s) { + if($s->subscription == 'subscribed') + return true; + } + return false; + } + + function build() + { + ?> +
    +
    + prepareGroup($_GET['s'], $_GET['n']); ?> +
    +
    + + * + * @version 1.0 + * @date 17 April 2013 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class NodeAffiliations extends WidgetBase +{ + + function WidgetLoad() + { + $this->registerEvent('pubsubaffiliations', 'onGroupMemberList'); + $this->registerEvent('pubsubaffiliationssubmited', 'onSubmit'); + } + + function prepareList($list) { //0:data 1:server 2:node + $affiliation = array("owner", "member", "none"); + $html = '
    '; + + foreach($list[0] as $item){ //0:jid 1:affiliation 2:subid + $html .= ' +
    + +
    + +
    +
    '; + } + + $ok = $this->genCallAjax('ajaxChangeAffiliation', "'".$list[1]."'", "'".$list[2]."'", "movim_parse_form('affiliationsManaging')"); + $html .= ' +
    +
    + + '.t('Validate').' +
    '; + return $html; + } + + function onSubmit($stanza) { + Notification::appendNotification(t('Affiliations saved'), 'success'); + RPC::commit(); + } + + function onGroupMemberList($list) { + $html = $this->prepareList($list); + RPC::call('movim_fill', 'memberlist', $html); + RPC::commit(); + } + + function ajaxChangeAffiliation($server, $node, $data){ + $r = new moxl\PubsubSetAffiliations(); + $r->setNode($node)->setTo($server)->setData($data) + ->request(); + } + + function ajaxGetGroupMemberList($server, $node){ + $r = new moxl\PubsubGetAffiliations(); + $r->setTo($server)->setNode($node) + ->request(); + } + + function build() + { + ?> + + diff --git a/app/widgets/NodeConfig/NodeConfig.php b/app/widgets/NodeConfig/NodeConfig.php new file mode 100644 index 000000000..915a7d386 --- /dev/null +++ b/app/widgets/NodeConfig/NodeConfig.php @@ -0,0 +1,119 @@ + + * + * @version 1.0 + * @date 12 March 2013 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class NodeConfig extends WidgetBase +{ + + function WidgetLoad() + { + $this->registerEvent('pubsubconfig', 'onConfigForm'); + $this->registerEvent('pubsubconfigsubmited', 'onGroupConfig'); + $this->registerEvent('deletionsuccess', 'onGroupDeleted'); + } + + function onGroupDeleted($server) { + $html = ' + + '.t("Return to %s's list of groups", $server).' +

    '; + + Notification::appendNotification(t('Group deleted'), 'success'); + RPC::call('movim_fill', 'handlingmessages', $html); + RPC::commit(); + } + + function onGroupConfig($stanza) { + Notification::appendNotification(t('Group configuration saved'), 'success'); + RPC::commit(); + } + + function onConfigForm($form) { + $submit = $this->genCallAjax('ajaxSubmitConfig', "movim_parse_form('config')", "'".$form[1]."'", "'".$form[2]."'"); + $html = ' +
    '. + $form[0]. + ' +

    + + '.t('Validate').' + +
    +
    +
    '; + + RPC::call('movim_fill', 'groupconfiguration', $html); + RPC::commit(); + } + + function ajaxGroupConfig($server, $node){ + $r = new moxl\PubsubGetConfig(); + $r->setTo($server) + ->setNode($node) + ->request(); + } + + function ajaxGroupDelete($server, $node){ + $nd = new modl\NodeDAO(); + $nd->deleteNode($server, $node); + + $r = new moxl\GroupDelete(); + $r->setTo($server) + ->setNode($node) + ->request(); + } + + function ajaxSubmitConfig($data, $server, $node){ + $r = new moxl\PubsubSetConfig(); + $r->setTo($server) + ->setNode($node) + ->setData($data) + ->request(); + } + + function build() + { + ?> + + + diff --git a/app/widgets/Notification/Notification.php b/app/widgets/Notification/Notification.php new file mode 100644 index 000000000..326adc115 --- /dev/null +++ b/app/widgets/Notification/Notification.php @@ -0,0 +1,51 @@ + + * + * @version 1.0 + * @date 16 juin 2011 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Notification extends WidgetCommon +{ + function WidgetLoad() + { + $this->addcss('notification.css'); + $this->addjs('notification.js'); + $this->registerEvent('pubsuberror', 'onPubsubError'); + } + + static function appendNotification($message, $type = 'info') + { + $id = $message.rand(0, 1500); + $html = '
    '.$message.'
    '; + + RPC::call('removeDiff', 'notification', $html); + RPC::commit(); + } + + function onPubsubError($error) { + Notification::appendNotification($error, 'error'); + } + + function build() + { + ?> +
    + +
    + Z#!uo=+xql)L&@>;2m%@$=-x? zM$-hxbix{Iuz{M^0sTzBcgTtvp#Mw2&lRE(a}Mz!V;n@u9AhaR>zRJvi1sQs8RmwC w_i)m6W_U7Pyv^FHEP(*DOe5~oe?U4bUNvYBn8SRFnE(I)07*qoM6N<$f^N8H-~a#s literal 0 HcmV?d00001 diff --git a/app/widgets/Notification/img/info.png b/app/widgets/Notification/img/info.png new file mode 100644 index 0000000000000000000000000000000000000000..2a4d2bb8a32a751480884487f2b086af04c63997 GIT binary patch literal 237 zcmV|B*O z7S&`6X9~n3YXW8oKL`wh->|I$r+JLy27wVMXNS%T&WJR6mHSMpnjYgnT&!{eZ~Wrz na=)?!YGA;R*oAw&)Ew~va^o1(q0LZ500000NkvXXu0mjfWxie7 literal 0 HcmV?d00001 diff --git a/app/widgets/Notification/img/success.png b/app/widgets/Notification/img/success.png new file mode 100644 index 0000000000000000000000000000000000000000..a59cbef14954cb28fc2160f7835abafd39c4c34d GIT binary patch literal 319 zcmV-F0l@x=P)%k`G!uY76v^-OFSj;f#k-d=3G>+?QER%`dU|z?2gSkYv z-er_bzG4TD4Q3dmtvqg7oHEw%9!{r}6Z5HRyoI(`*+n0@>WYgn?*G&r@eQ22G@}Hi RdHMhV002ovPDHLkV1fguh=c$D literal 0 HcmV?d00001 diff --git a/app/widgets/Notification/img/warning.png b/app/widgets/Notification/img/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..abf21488eb61f1eaba2f9b37edd05025bf31c8b8 GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`fu1goAr`%NCvW6sFyJ_B(fWV> zBaw2~tc4*4rr9Ft4ILJYToN030xVYw^eOT`l%3QX>&SC*mOcZ+=`&mn_ZdZd8FWm# l)8E(z{hsQ6?8?l~Oj@x%ac6IJ>;)Rm;OXk;vd$@?2>? + * + * @version 1.0 + * @date 16 juin 2011 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Notifs extends WidgetCommon +{ + function WidgetLoad() + { + $this->addcss('notifs.css'); + $this->addjs('notifs.js'); + $this->registerEvent('notification', 'onNotification'); + $this->registerEvent('notificationdelete', 'onNotificationDelete'); + $this->registerEvent('notifications', 'displayNotifications'); + $this->registerEvent('nonotification', 'onNoNotification'); + } + + /* + * Retrieve all the notifications + */ + function ajaxGetNotifications() { + $p = new moxl\NotificationGet(); + $p->setTo($this->user->getLogin()) + ->request(); + } + + /* + * Delete a notification item + */ + function ajaxDeleteNotification($id) { + $d = new moxl\NotificationItemDelete(); + $d->setTo($this->user->getLogin()) + ->setId($id) + ->request(); + } + + /* + * Create the notification element from the inbox item + * @param SimpleXMLElement $item + */ + function onNotification($item) { + $arr = explodeURI((string)$item->entry->link[0]->attributes()->href); + $post = end(explode('/', $arr['node'])); + + $notifs = Cache::c('activenotifs'); + + $request = $this->genCallAjax( + "ajaxGetComments", + "'".$this->user->getLogin()."'", + "'".$post."'"); + + $delete = $this->genCallAjax( + "ajaxDeleteNotification", + "'".(string)$item->attributes()->id."'"); + + $nhtml = ' + +
  • + + '. + (string)$item->entry->source->author->name.' + - '.prepareDate(strtotime((string)$item->entry->published)).'
    '. + (string)$item->entry->content.' +
    + + '.t('Delete').' +
    +
  • + '; + + $notifs[(string)$item->attributes()->id] = $nhtml; + + Cache::c('activenotifs', $notifs); + } + + /* + * In notification deletion + * @param string $id + */ + function onNotificationDelete($id) { + $notifs = Cache::c('activenotifs'); + unset($notifs[$id]); + Cache::c('activenotifs', $notifs); + + RPC::call('movim_fill', 'notifs', $this->prepareNotifs()); + } + + /* + * Display all the notifications to the browser + */ + function displayNotifications() { + RPC::call('movim_fill', 'notifs', $this->prepareNotifs()); + } + + /* + * Display all the notifications to the browser if there is no new + * notifications + */ + function onNoNotification() { + RPC::call('movim_fill', 'notifs', $this->prepareNotifs()); + } + + /* + * Create the list of notifications + * @return string + */ + function prepareNotifs() + { + $notifsnum = 0; + + $html .= ' +
    + + '.t('Refresh').' + +
      '; + // XMPP notifications + $notifs = Cache::c('activenotifs'); + + if($notifs == false) + $notifs = array(); + + + if(sizeof($notifs) != 0) { + $notifsnum += sizeof($notifs); + + $html .= ' +
    • '. + t('Notifications').' + '.sizeof($notifs).' +
    • '; + + foreach($notifs as $n => $val) { + if($val == 'sub') + $html .= $this->prepareNotifInvitation($n); + else + $html .= $val; + } + + } + + // Contact request pending + $cd = new \modl\ContactDAO(); + $subscribes = $cd->getRosterSubscribe(); + + if(sizeof($subscribes) != 0) { + $notifsnum += sizeof($subscribes); + + $html .= ' +
    • '. + t('Contact request pending').' + '.sizeof($subscribes).' +
    • '; + + foreach($subscribes as $s) { + $html .= ' +
    • + + + '. + $s->getTrueName().' + +
    • '; + } + + } + + + $html .= ' +
    +
    '; + + $notifsnew = ''; + if($notifsnum > 0) + $notifsnew = 'class="red"'; + + $html = ' +
    + '. + $notifsnum.' + +
    '.$html; + + return $html; + } + + function ajaxSubscribed($jid) { + $p = new moxl\PresenceSubscribed(); + $p->setTo($jid) + ->request(); + } + + function ajaxRefuse($jid) { + $p = new moxl\PresenceUnsubscribed(); + $p->setTo($jid) + ->request(); + + $notifs = Cache::c('activenotifs'); + unset($notifs[$jid]); + + Cache::c('activenotifs', $notifs); + + RPC::call('movim_fill', 'notifs', $this->prepareNotifs()); + + RPC::commit(); + } + + function ajaxAccept($jid, $alias) { + $r = new moxl\RosterAddItem(); + $r->setTo($jid) + ->request(); + + $p = new moxl\PresenceSubscribe(); + $p->setTo($jid) + ->request(); + + $p = new moxl\PresenceSubscribed(); + $p->setTo($jid) + ->request(); + + $notifs = Cache::c('activenotifs'); + + unset($notifs[$jid]); + + Cache::c('activenotifs', $notifs); + + RPC::call('movim_fill', 'notifs', $this->prepareNotifs()); + + RPC::commit(); + } + + /* + * Prepare a notification for incoming invitation + * @return string + */ + function prepareNotifInvitation($from) { + $html .= ' +
  • +
    +

    '.$from.' '.t('wants to talk with you'). '

    + '. + t("Add").' + '. + t("Decline").' + +
    +
    +
  • '; + + return $html; + } + + function build() + { + ?> +
    + prepareNotifs(); ?> +
    + 0) { + RequestPermission(notification); + } + + if(document_focus == false) { + var icon = ''; + var title = params[0]; + var body = params[1]; + + var popup = window.webkitNotifications.createNotification(icon, title, body); + popup.show(); + setTimeout(function(){ + popup.cancel(); + }, '30'); + } +} +*/ diff --git a/app/widgets/Poller/Poller.php b/app/widgets/Poller/Poller.php new file mode 100644 index 000000000..d7495e2c6 --- /dev/null +++ b/app/widgets/Poller/Poller.php @@ -0,0 +1,35 @@ + + * + * @version 1.0 + * @date 20 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Poller extends WidgetBase +{ + function WidgetLoad() + { + // We add the javascript that does the job. + $this->addjs('poller.js'); + // And that's it! + } + + function build() + { + } +} + +?> diff --git a/app/widgets/Poller/poller.js b/app/widgets/Poller/poller.js new file mode 100644 index 000000000..a48772cce --- /dev/null +++ b/app/widgets/Poller/poller.js @@ -0,0 +1,70 @@ +var empty_count = 0; + +/** + * Attach a callback function to an event. + */ +function movimRegisterPollHandler(type, func) +{ + if(!(type in movimPollHandlers)) { + movimPollHandlers[type] = new Array(); + } + movimPollHandlers[type].push(func); +} + +/** + * Polls the server. + */ +function movim_poll() +{ + poller = rpc.make_xmlhttp(); + poller.open('GET', BASE_URI+'jajax.php?do=poll', true); + + poller.onreadystatechange = function() + { + if(poller.readyState == 4) + { + if(poller.status == 200) { + // Handling poll return. + if(poller.response == null) { + + if(empty_count == 3) + movim_disconnect('&err=session'); + else + empty_count++; + } else { + empty_count = 0; + rpc.handle_rpc_json(poller.response); + } + } else if(poller.status == 500 || poller.status == 400) { + movim_disconnect('&err=internal'); + } + + if(poller.status == 200) { + // Restarting polling. + movim_poll(); + } + + } + }; + + poller.send(); +} + +function movim_disconnect(error) +{ + var url = window.location.href; + var urlparts = url.split('/'); + var txt = urlparts[0]+'//'; + for(i = 2; i < urlparts.length-1; i++) { + txt = txt+urlparts[i]+'/' + } + window.location.replace(txt+'index.php?q=disconnect' + error); +} + +function halt_poll() +{ + poller.abort(); +} + +// Adding the polling to onload event. +movim_add_onload(movim_poll); diff --git a/app/widgets/Profile/Profile.php b/app/widgets/Profile/Profile.php new file mode 100644 index 000000000..607d969c2 --- /dev/null +++ b/app/widgets/Profile/Profile.php @@ -0,0 +1,144 @@ + + * + * @version 1.0 + * @date 20 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Profile extends WidgetCommon +{ + + private static $status; + + function WidgetLoad() + { + $this->addcss('profile.css'); + $this->addjs('profile.js'); + $this->registerEvent('myvcard', 'onMyVcardReceived'); + $this->registerEvent('mypresence', 'onMyPresence'); + } + + function onMyVcardReceived($vcard = false) + { + $html = $this->prepareVcard($vcard); + RPC::call('movim_fill', 'profile', $html); + } + + function onMyPresence() + { + RPC::call('movim_fill', 'statussaved', '✔ '.t('Saved')); + Notification::appendNotification(t('Status updated'), 'success'); + } + + function ajaxSetStatus($status) + { + $status = htmlspecialchars(rawurldecode($status)); + // We update the cache with our status and presence + $presence = Cache::c('presence'); + Cache::c( + 'presence', + array( + 'status' => $status, + 'show' => $presence['show'], + ) + ); + + switch($presence['show']) { + case 'chat': + $p = new moxl\PresenceChat(); + $p->setStatus($status)->request(); + break; + case 'away': + $p = new moxl\PresenceAway(); + $p->setStatus($status)->request(); + break; + case 'dnd': + $p = new moxl\PresenceDND(); + $p->setStatus($status)->request(); + break; + case 'xa': + $p = new moxl\PresenceXA(); + $p->setStatus($status)->request(); + break; + default : + $p = new moxl\PresenceChat(); + $p->setStatus($status)->request(); + break; + } + } + + function prepareVcard($vcard = false) + { + $cd = new modl\ContactDAO(); + $contact = $cd->get($this->user->getLogin()); + + $presence = Cache::c('presence'); + + if(isset($contact)) { + $me = $contact; + + // My avatar + $html .= ' + + + '; + + // Contact general infos + $html .= ' +

    '.$me->getTrueName().'

    '; + + if($this->testIsSet($me->name)) + $html .= $me->name.' '; + else + $html .= $me->getTrueName().' '; + + if($this->testIsSet($me->url)) + $html .= '
    '.$me->url.''; + + $html .= ' +
    + +
    +
    + '; + } else { + $html .= ' + '.t('No profile yet ?').'

    + '.t("Create my vCard").'

    '; + } + + return $html; + } + + function build() + { + ?> + +
    + prepareVcard(); + ?> +
    + + * + * @version 1.0 + * @date 20 October 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class ProfileData extends WidgetBase +{ + function WidgetLoad() + { + $this->addjs('profiledata.js'); + $this->registerEvent('locationpublished', 'onLocationPublished'); + $this->registerEvent('locationpublisherror', 'onLocationPublishError'); + } + + function ajaxLocationPublish($pos) + { + $pos = json_decode($pos); + if($pos->place_id) { + $geo = array( + 'latitude' => (string)$pos->lat, + 'longitude' => (string)$pos->lon, + 'altitude' => (string)$pos->alt, + 'country' => (string)$pos->address->country, + 'countrycode' => (string)$pos->address->country_code, + 'region' => (string)$pos->address->county, + 'postalcode' => (string)$pos->address->postcode, + 'locality' => (string)$pos->address->city, + 'street' => (string)$pos->address->path, + 'building' => (string)$pos->address->building, + 'text' => (string)$pos->display_name, + 'uri' => ''//'http://www.openstreetmap.org/'.urlencode('?lat='.(string)$pos->lat.'&lon='.(string)$pos->lon.'&zoom=10') + ); + + $p = new moxl\LocationPublish(); + $p->setTo($this->user->getLogin()) + ->setGeo($geo) + ->request(); + } else { + Notification::appendNotification(t('Wrong position'), 'error'); + } + } + + function onLocationPublished($me) + { + $html = $me->getPlace(); + RPC::call('movim_fill', 'mapdata', $html); + + Notification::appendNotification(t('Location updated'), 'success'); + RPC::call('movim_delete', 'mapdiv'); + RPC::commit(); + } + + function onLocationPublishError($error) + { + Notification::appendNotification($error, 'error'); + + RPC::call('movim_delete', 'mapdiv'); + RPC::call('movim_delete', 'mapdata'); + RPC::commit(); + } + + function prepareProfileData() + { + $submit = $this->genCallAjax('ajaxLocationPublish', "getMyPositionData()"); + + $cd = new modl\ContactDAO(); + $c = $cd->get($this->user->getLogin()); + + if($c->loctimestamp) { + $data = prepareDate(strtotime($c->loctimestamp)).'

    '; + $data .= $c->getPlace(); + } else { + $data = ''; + } + + $html = ''; + + $html .= ' +

    '.t('Location').'

    + '; + + return $html; + } + + function build() + { + echo $this->prepareProfileData(); + } +} diff --git a/app/widgets/ProfileData/profiledata.js b/app/widgets/ProfileData/profiledata.js new file mode 100644 index 000000000..5fd053bdc --- /dev/null +++ b/app/widgets/ProfileData/profiledata.js @@ -0,0 +1,61 @@ +var myposition = 0; + +function getMyPositionData() { return myposition; } + +window.cb = function cb(json) { + document.getElementById('mapdata').innerHTML = json.display_name + ',' + json.address.city; + myposition = JSON.stringify(json); +} + +function hidePositionChoice() +{ + document.querySelector("#mypossubmit").style.display = 'none'; + document.querySelector("#myposrefuse").style.display = 'none'; +} + +function getMyPosition() { + if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition( + function (position) { + + document.querySelector("#mapdiv").style.display = 'block'; + + var map = L.map("mapdiv").setView([position.coords.latitude ,position.coords.longitude], 11); + + L.tileLayer("http://tile.openstreetmap.org/{z}/{x}/{y}.png", { + attribution: "", + maxZoom: 18 + }).addTo(map); + var marker = L.marker([position.coords.latitude ,position.coords.longitude]).addTo(map) + + var s = document.createElement('script'); + s.src = 'http://nominatim.openstreetmap.org/reverse?json_callback=cb&format=json&lat='+position.coords.latitude+'&lon='+position.coords.longitude+'&zoom=27&addressdetails=1'; + document.getElementsByTagName('head')[0].appendChild(s); + + document.querySelector("#mypossubmit").style.display = 'block'; + }, + // next function is the error callback + function (error) + { + switch(error.code) + { + case error.TIMEOUT: + alert ('Timeout'); + break; + case error.POSITION_UNAVAILABLE: + alert ('Position unavailable'); + break; + case error.PERMISSION_DENIED: + alert ('Permission denied'); + break; + case error.UNKNOWN_ERROR: + alert ('Unknown error'); + break; + } + } + ); + } + else { + + } +} diff --git a/app/widgets/PubsubSubscriptionConfig/PubsubSubscriptionConfig.php b/app/widgets/PubsubSubscriptionConfig/PubsubSubscriptionConfig.php new file mode 100644 index 000000000..9cbcf950d --- /dev/null +++ b/app/widgets/PubsubSubscriptionConfig/PubsubSubscriptionConfig.php @@ -0,0 +1,83 @@ + + * + * @version 1.0 + * @date 24 March 2013 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class PubsubSubscriptionConfig extends WidgetBase +{ + + function WidgetLoad() + { + $this->registerEvent('groupsubscribedlist', 'onGroupSubscribedList'); + $this->registerEvent('groupremoved', 'onGroupRemoved'); + } + + function prepareList($list) { + if(is_array($list[0])){ + $html = '
      '; + foreach($list as $item){ + $delete = $this->genCallAjax('ajaxDeleteFromGroupSubscribedList', "'".$item[0]."'", "'".$item[1]."'"); + $html .= ' +
    • + '.t('Delete').' + '.$item[2].' +
    • '; + } + $html .= '
    '; + return $html; + } + else return "No groups found"; + } + + function onGroupRemoved($node) { + RPC::call('movim_delete', 'group'.$node); + Notification::appendNotification(t('%s has been removed from your public groups', $node), 'success'); + RPC::commit(); + } + + function onGroupSubscribedList($list) { + $html = $this->prepareList($list); + RPC::call('movim_fill', 'listconfig', $html); + } + + function ajaxDeleteFromGroupSubscribedList($node, $server){ + $r = new moxl\PubsubSubscriptionListRemove(); + $r->setNode($node) + ->setTo($server) + ->setFrom($this->user->getLogin()) + ->request(); + } + + function ajaxGetGroupSubscribedList(){ + $r = new moxl\PubsubSubscriptionListGet(); + $r->request(); + } + + function build() + { + ?> +
    +
    + +
    +
    + diff --git a/app/widgets/Roster/Roster.php b/app/widgets/Roster/Roster.php new file mode 100644 index 000000000..264af0dfd --- /dev/null +++ b/app/widgets/Roster/Roster.php @@ -0,0 +1,402 @@ + + * + * @version 1.0 + * @date 30 August 2010 + * + * Copyright (C)2010 MOVIM project + * + * See COPYING for licensing information. + */ + +class Roster extends WidgetBase +{ + private $grouphtml; + + function WidgetLoad() + { + $this->addcss('roster.css'); + $this->addjs('roster.js'); + $this->registerEvent('roster', 'onRoster'); + $this->registerEvent('contactadd', 'onRoster'); + $this->registerEvent('contactremove', 'onRoster'); + $this->registerEvent('presence', 'onPresence'); + + $this->cached = false; + } + + function onPresence($presence) + { + $arr = $presence->getPresence(); + RPC::call('incomingPresence', $arr['jid'], $arr['presence_txt']); + } + + function onRoster() + { + $html = $this->prepareRoster(); + RPC::call('movim_fill', 'rosterlist', $html); + RPC::call('sortRoster'); + } + + /** + * @brief Force the roster refresh + * @returns + * + * + */ + function ajaxRefreshRoster() + { + $r = new moxl\RosterGetList(); + $r->request(); + } + + /** + * @brief Generate the HTML for a roster contact + * @param $contact + * @param $inner + * @returns + * + * + */ + function prepareRosterElement($contact, $caps = false) + { + $html = ''; + + $html .= '
  • jid.'" + >'; + + $type = ''; + + if($caps) { + foreach($caps as $c) { + if($c->node == $contact->node.'#'.$contact->ver) { + $type = $c->type; + } + } + } + + $html .= '
    jid."'").'">
    '; + + if($type == 'handheld') + $html .= '
    '; + + if($type == 'web') + $html .= '
    '; + + if($type == 'bot') + $html .= '
    '; + + if((isset($contact->tuneartist) && $contact->tuneartist != '') || + (isset($contact->tunetitle) && $contact->tunetitle != '')) + $html .= '
    '; + + $html .= 'jid).'" + > + '. + $contact->getTrueName(); + $html .= '
    '; + if($contact->rosterask == 'subscribe') + $html .= " #"; + if($contact->ressource != '') + $html .= ' '.$contact->ressource.''; + $html .= ' +
    '; + + $html .= '
  • '; + + return $html; + } + + /** + * @brief Create the HTML for a roster group and add the title + * @param $contacts + * @param $i + * @returns html + * + * + */ + private function prepareRosterGroup($contacts, &$i, $caps) + { + $j = $i; + // We get the current name of the group + $currentgroup = $contacts[$i]->group; + + // Temporary array to prevent duplicate contact + $duplicate = array(); + + // We grab all the contacts of the group + $grouphtml = ''; + while(isset($contacts[$i]) && $contacts[$i]->group == $currentgroup) { + //if(!in_array($contacts[$i]->jid, $duplicate)) { + $grouphtml .= $this->prepareRosterElement($contacts[$i], $caps); + array_push($duplicate, $contacts[$i]->jid); + //} + $i++; + } + + // And we add the title at the head of the group + if($currentgroup == '') + $currentgroup = t('Ungrouped'); + + $groupshown = ''; + // get the current showing state of the group and the offline contacts + $groupState = Cache::c('group'.$currentgroup); + + if($groupState == true) + $groupshown = 'groupshown'; + + $count = $i-$j; + + $grouphtml = ' +
    +

    '. + $currentgroup.' - '.$count.' +

    '.$grouphtml.' +
    '; + + return $grouphtml; + } + + /** + * @brief Here we generate the roster + * @returns + * + * + */ + function prepareRoster() + { + $contactdao = new \modl\ContactDAO(); + $contacts = $contactdao->getRoster(); + + $html = ''; + + $rd = new \modl\RosterLinkDAO(); + + $capsdao = new modl\CapsDAO(); + $caps = $capsdao->getAll(); + + if(count($contacts) > 0) { + $i = 0; + + while($i < count($contacts)) + $html .= $this->prepareRosterGroup($contacts, $i, $caps); + + } else { + $html .= ''; + } + + return $html; + } + + /** + * @brief Adding a new contact from the Rostermenu + * @param $jid + * @param $alias + * @returns + * + * + */ + function ajaxAddContact($jid, $alias) { + $r = new moxl\RosterAddItem(); + $r->setTo($jid) + ->request(); + + $p = new moxl\PresenceSubscribe(); + $p->setTo($jid) + ->request(); + } + + /** + * @brief Toggling boolean variables in the Cache + * @param $param + * @returns + * + * + */ + function ajaxToggleCache($param){ + //$bool = !currentValue + $bool = (Cache::c($param) == true) ? false : true; + //toggling value in cache + Cache::c($param, $bool); + //$offline = new value of wether offline are shown or not + $offline = Cache::c('offlineshown'); + + if($param == 'offlineshown') { + RPC::call('showRoster', $bool); + } else + RPC::call('rosterToggleGroup', $param, $bool, $offline); + + RPC::call('focusContact'); + RPC::commit(); + } + + function ajaxToggleChat() + { + //$bool = !currentValue + $bool = (Cache::c('chatpop') == true) ? false : true; + //toggling value in cache + Cache::c('chatpop', $bool); + + RPC::call('movim_fill', 'chattoggle', $this->prepareChatToggle()); + + RPC::commit(); + } + + function prepareChatToggle() + { + $chatpop = Cache::c('chatpop'); + + if($chatpop) { + $arrow = 'expand'; + $ptoggle = 'openPopup();'; + $call = $this->genCallAjax('ajaxToggleChat'); + } else { + $arrow = 'contract'; + $ptoggle = 'closePopup();'; + $call = ''; + } + + $html = ' +
  • + +
  • '; + + return $html; + } + + /** + * @brief Show/Hide the Roster + */ + function ajaxShowHideRoster() { + $bool = (Cache::c('rostershow') == true) ? false : true; + Cache::c('rostershow', $bool); + RPC::call('showHideRoster', $bool); + RPC::commit(); + } + + function build() + { + $offlineshown = ''; + $offlineState = Cache::c('offlineshown'); + + $bool = Cache::c('rostershow'); + if($bool) + $rostershow = 'hide'; + + if($offlineState == true) + $offlineshown = 'offlineshown'; + ?> +
    +
      + prepareRoster(); ?> +
    + +
    + + + diff --git a/app/widgets/Roster/geany_run_script.sh b/app/widgets/Roster/geany_run_script.sh new file mode 100755 index 000000000..a384f5a9a --- /dev/null +++ b/app/widgets/Roster/geany_run_script.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +rm $0 + +./roster + +echo " + +------------------ +(program exited with code: $?)" + + +echo "Press return to continue" +#to be more compatible with shells like dash +dummy_var="" +read dummy_var diff --git a/app/widgets/Roster/img/away.png b/app/widgets/Roster/img/away.png new file mode 100644 index 0000000000000000000000000000000000000000..cc8fa897c5e173afba485fe924fb53f648ced5ff GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2comSQK*5Dp-y;YjHK@;M7UB8!1^ z83;4_RjY9T8ImQg5hcO-X(i=}MX3zs<>h*rdD+Fui3O>8`9{Rr!#oE`njxgN@xNA;IeSL literal 0 HcmV?d00001 diff --git a/app/widgets/Roster/img/background.png b/app/widgets/Roster/img/background.png new file mode 100644 index 0000000000000000000000000000000000000000..bf00678d5958f2e0381fb8060730f1f4019640c9 GIT binary patch literal 16871 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 literal 0 HcmV?d00001 diff --git a/app/widgets/Roster/img/bubbles.png b/app/widgets/Roster/img/bubbles.png new file mode 100644 index 0000000000000000000000000000000000000000..7ece2d1757936efc20a8e823a442cd64a352dfd0 GIT binary patch literal 262 zcmV+h0r~!kP)IYsNfw0?CiV+f38BrGAUz7Yp+eP6VgPq5|&sc_*m?W zEbDIYg=x;r`*Gl#5F%*f3R8T=GsPu#Lm8YPQ%{DYqHu`S8X>VlFG-Vs2#Il$7Hb|Y zF~kM>xJlASjqoY2evCT|aE{G@+ZyQ<*A@9=zz*I^7a3aku9}uA?%}PF&#_mO$&N85hd-)zl=oEI?!E;G^3UT5Aw*GvTTx`VpU7X?N2liS2z2@Kn{Qv*} M07*qoM6N<$f;|CoJOBUy literal 0 HcmV?d00001 diff --git a/app/widgets/Roster/img/dnd.png b/app/widgets/Roster/img/dnd.png new file mode 100644 index 0000000000000000000000000000000000000000..85bd04cbfd75448ab797dfb55466ec9a9f39c069 GIT binary patch literal 308 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2comSQK*5Dp-y;YjHK@;M7UB8!1^ z83;4_RjY9T8ImQg5hcO-X(i=}MX3zs<>h*rdD+Fui3O>8`9ao%aSXBO zeS5){k1=*R!HX>qPf7rQsIh8^hYh*G{7;8AjI(FO)Fg^wGV0zGQZoSwbfu{mYN zq~LpV{uC9bM6LWLXytI?d7*~$Ot-7t3Huq|b^5w79GKO^z)=50U10jf0yYWef8Ga} zlLJG=zE)M-cw2ODhS8}{VF7`+j{mSZ89jTC5ZBU4>(4&-3;9|&$2IU`_f6)GOIbPB x7n{7_BN?_Uvr+wt2n*+n1v?|ZUSeVh|FGEP^fY;?T|mb(c)I$ztaD0e0svgAbk_g? literal 0 HcmV?d00001 diff --git a/app/widgets/Roster/img/earth.png b/app/widgets/Roster/img/earth.png new file mode 100644 index 0000000000000000000000000000000000000000..53dc9869bfd393d37e04eadf20767adc795600a5 GIT binary patch literal 390 zcmV;10eSw3P)8~P>3I$WRqMSyLiNxNUz6lwRrLtJMSR)6+Uc5S_3*Uqc|#gVh_$Som0_)J>22p1HgZjve2A` zq@*E?p$k{|hJyk~ISbwHi_B}GStsbnSImY#rg4<19n*R+4-{S+85d zH23)Cg$68>^>z2OvHalXO=G-pF(XW|jd2Ipsm5L3S>r$SDQs*I4E^1Dq~~7bP0l+XkK`~E4> literal 0 HcmV?d00001 diff --git a/app/widgets/Roster/img/music.png b/app/widgets/Roster/img/music.png new file mode 100644 index 0000000000000000000000000000000000000000..7d2359b3cf25f3331665ae28a6a65b5957037fb5 GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`lRaG=Lo9l)Ufjre$U%hdfyg8? zXN%V46z=671zg&WG6xK090fKvB_z)hncvE;RdL+=<^7n?|M>6iUNuY7BxB=I0Zp9^ zPW{4a@+YTGi+J3z+o{OGqPRhG?SsPehuM(1bg zEhTr1{%%~ezp*wgCH&g{{0k48+^ejwq}oneBzHpiw1}{7q<>~N(0L4=u6{1-oD!M< DY6(!G literal 0 HcmV?d00001 diff --git a/app/widgets/Roster/img/offline.png b/app/widgets/Roster/img/offline.png new file mode 100644 index 0000000000000000000000000000000000000000..be8e41afded0d28573b0c590cc517677e6130ba3 GIT binary patch literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2comSQK*5Dp-y;YjHK@;M7UB8!1^ z83;4_RjY9T8ImQg5hcO-X(i=}MX3zs<>h*rdD+Fui3O>8`9>yU#$>%;m@Dy|9-IBi_MrF4}_9dzSXoSS~jA<92-Wh38lo%wVu7I-ADC;A$q!@Sy(>i%`0hA#;?1FN@HHu2q*xW8dvH zPmR>;HGE#}=$f*2mHPX?AN*FV(u&MpyyDg88{hvbEiGXbm>3#+{kY-#8mVoP+O)78&qol`;+0CMDNLjV8( literal 0 HcmV?d00001 diff --git a/app/widgets/Roster/img/online.png b/app/widgets/Roster/img/online.png new file mode 100644 index 0000000000000000000000000000000000000000..f432d267149fa64ceb39f3ace9c30a0c9b935d7b GIT binary patch literal 317 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2comSQK*5Dp-y;YjHK@;M7UB8!1^ z83;4_RjY9T8ImQg5hcO-X(i=}MX3zs<>h*rdD+Fui3O>8`92?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4MCOcUjuS8D9XYds>B*1p`8AB|BJaM870YV|dYZx0)z4*}Q$iB} DI-rNi literal 0 HcmV?d00001 diff --git a/app/widgets/Roster/img/server_error.png b/app/widgets/Roster/img/server_error.png new file mode 100644 index 0000000000000000000000000000000000000000..b804ce0d532ac0fc33d2526643af69840b33e469 GIT binary patch literal 423 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2comSQK*5Dp-y;YjHK@;M7UB8!1^ z83;4_RjY9T8ImQg5hcO-X(i=}MX3zs<>h*rdD+Fui3O>8`9wnllpiN%-)5^B09PumrIg-*+9C$qL{z%V>oV9e7(9*TDw(zD|Fqs%Cz15zZ zv%kEqX4{%gXY3gH8;<|9V$jz*ox}S>oFVFMsrUksBO7;H^{L*UxPG^vz<~-L&!SiA zoj)8ew0~C!WliN=Jdx$knbSd^Vqz0#D**!TYM}ED3x6F<#la=6}$8 ztF?=6CLMu>JX? z`Lpa?QfJ;RzBxU=^uhs|f)DH~8K0es;(oAHGko6hwb%C4i$*+-G2comSQK*5Dp-y;YjHK@;M7UB8!1^ z83;4_RjY9T8ImQg5hcO-X(i=}MX3zs<>h*rdD+Fui3O>8`9af!aSXBO zeS5){ugO7#