1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/movim_ynh.git synced 2024-09-03 19:46:19 +02:00

update to movim 0.9-git2015-09-22

This commit is contained in:
src386 2015-09-22 08:18:52 +02:00
parent 451a5b0499
commit 2364e0e077
27 changed files with 298 additions and 153 deletions

View file

@ -7,23 +7,23 @@ Warning: BETA.
You need a valid SSL certificate to use Movim, auto-signed is not allowed.
Current Movim version : 0.9 git2015-09-10
Current Movim version : 0.9 git2015-09-22
**Changelog**
0.9b 2015-0
- Update to upstream Movim 0.9 git2015-09-10
- Add notes in README about public pods & whitelisting
- Update to upstream Movim 0.9 git2015-09-22.
- Add notes in README about public pods & whitelisting.
- script/install now check if path is empty.
- script/remove now delete /etc/php/fpm/pool.d/movim.conf (fix #8).
- script/remove now delete 'movim' user only after Movim service is stopped.
- script/remove now stop php5-fpm in order to remove Movim user
- script/remove now stop php5-fpm in order to remove Movim user.
- script/update now updates php dependancies (composer update).
- conf/movim.service now has a PID and a syslog identifier.
- conf/movim.service starts after mysql.service.
- conf/movim.service is now located in /etc/systemd/system
- conf/movim.service is now located in /etc/systemd/system.
- conf/movim.init starts after mysql.
- conf/nginx.conf : proxy_read_timeout and proxy_send_timeout removed (default is 60s)
- conf/nginx.conf : proxy_read_timeout and proxy_send_timeout removed (default is 60s).
- conf/php-fpm.conf add timezone parameter.
0.8b 2015-08-24

1
TODO
View file

@ -1 +0,0 @@
- systemd Log to /var/log/movim/

View file

@ -10,6 +10,8 @@ class Conference extends Model {
public $autojoin;
public $status;
public $connected = false;
public function __construct() {
$this->_struct = '
{

View file

@ -90,8 +90,14 @@ class Postn extends Model {
switch($c->attributes()->type) {
case 'html':
case 'xhtml':
if($c->getName() == 'content') return $c->children()->asXML();
else return (string)$c->asXML();
$dom = new \DOMDocument('1.0', 'utf-8');
$import = dom_import_simplexml($c->children());
if($import == null) {
$import = dom_import_simplexml($c);
}
$element = $dom->importNode($import, true);
$dom->appendChild($element);
return (string)$dom->saveHTML();
break;
case 'text':
default :
@ -293,6 +299,14 @@ class Postn extends Model {
return false;
}
public function getUUID() {
if(substr($this->nodeid, 10) == 'urn:uuid:') {
return $this->nodeid;
} else {
return 'urn:uuid:'.generateUUID($this->nodeid);
}
}
public function isMicroblog() {
if($this->node == "urn:xmpp:microblog:0")
return true;

View file

@ -4,7 +4,7 @@
<ul class="thick divided">
<li class="condensed">
<span class="icon bubble color green"><i class="zmdi zmdi-info"></i></span>
<p>{$c->__('about.info')} <a href="http://www.gnu.org/licenses/agpl-3.0.html">GNU Affero General Public License v3</a>.</p>
<p class="all">{$c->__('about.info')} <a href="http://www.gnu.org/licenses/agpl-3.0.html">GNU Affero General Public License v3</a>.</p>
</li>
<li class="subheader">{$c->__('about.thanks')}</li>
<li class="condensed">

View file

@ -72,7 +72,7 @@ class AdminMain extends WidgetBase
$cd = new \Modl\ConfigDAO();
$config = $cd->get();
$l = Locale::start();
$l = Movim\i18n\Locale::start();
$this->view->assign('conf', $cd->get());
$this->view->assign('logs',

View file

@ -8,10 +8,6 @@ class Blog extends WidgetBase {
function display()
{
/*if(!$this->get('f')) {
return;
}*/
if($this->_view == 'grouppublic') {
$from = $this->get('s');
$node = $this->get('n');

View file

@ -28,7 +28,15 @@
{/if}
</li>
{else}
<li class="condensed">
<li class="condensed action">
<div class="action">
<a
href="{$c->route('feed', array($server, $node))}"
target="_blank"
>
<i class="zmdi zmdi-portable-wifi"></i> Atom
</a>
</div>
<span class="icon gray">
<i class="zmdi zmdi-pages"></i>
</span>

View file

@ -72,20 +72,23 @@ class Chat extends WidgetBase
&& $message->type != 'groupchat') {
$avatar = $contact->getPhoto('s');
if($avatar == false) $avatar = null;
Notification::append('chat|'.$from, $contact->getTrueName(), $message->body, $avatar, 4);
Notification::append(
'chat|'.$from,
$contact->getTrueName(),
$message->body,
$avatar,
4,
$this->route('chat', $contact->jid)
);
}
RPC::call('movim_fill', $from.'_state', $contact->jid);
// If the message is from me
} /*else {
} else {
// If the message is from me we reset the notif counter
$from = $message->jidto;
$contact = $cd->get();
}*
$me = $cd->get();
if($me == null) {
$me = new \Modl\Contact;
}*/
$n = new Notification;
$n->ajaxClear('chat|'.$from);
}
if(!preg_match('#^\?OTR#', $message->body)) {
RPC::call('Chat.appendMessage', $this->prepareMessage($message));

View file

@ -83,7 +83,7 @@ var Chat = {
}
bubble.querySelector('div').className = '';
} else {
} else if(Chat.left != null) {
if(message.session == message.jidfrom) {
bubble = Chat.right.cloneNode(true);
if(Chat.previous == 'right') {
@ -124,6 +124,7 @@ var Chat = {
MovimWebsocket.attach(function() {
var jid = document.querySelector('#chat_widget').dataset.jid;
if(jid) {
MovimTpl.showPanel();
Chat_ajaxGet(jid);
}
});

View file

@ -1,3 +1,7 @@
<div id="chat_widget" {if="$jid"}data-jid="{$jid}"{/if}>
{$c->prepareEmpty()}
{if="$jid"}
{$c->prepareChat($jid)}
{else}
{$c->prepareEmpty()}
{/if}
</div>

View file

@ -36,7 +36,7 @@ class Config extends WidgetBase
/* We load the user configuration */
$this->user->reload();
$l = Locale::start();
$l = Movim\i18n\Locale::start();
$view->assign('languages', $l->getList());
$view->assign('me', $this->user->getLogin());

View file

@ -46,9 +46,24 @@ class Menu extends WidgetBase
$title = $post->title;
}
if(!$post->isMine()) Notification::append('news', $contact->getTrueName(), $title, $contact->getPhoto('s'), 2);
if(!$post->isMine())
Notification::append(
'news',
$contact->getTrueName(),
$title,
$contact->getPhoto('s'),
2,
$this->route('news', $post->nodeid)
);
} else {
Notification::append('news', $post->title, $post->node, null, 2);
Notification::append(
'news',
$post->title,
$post->node,
null,
2,
$this->route('news', $post->nodeid)
);
}
$this->onStream($count);

View file

@ -29,16 +29,19 @@ class Notification extends WidgetBase
$session = Session::start();
$notifs = $session->get('notifs');
RPC::call('Notification.desktop', $title, $body, $picture);
RPC::call('Notification.desktop', $title, $body, $picture, $action);
$notifs_key = $session->get('notifs_key');
if($notifs_key != null && $key == $notifs_key) return;
if($notifs == null) $notifs = array();
$explode = explode('|', $key);
$first = reset($explode);
if($notifs_key != null && $first == $notifs_key) return;
RPC::call('Notification.android', $title, $body, $picture, $action);
if(array_key_exists($first, $notifs)) {
$notifs[$first]++;
} else {
@ -58,7 +61,7 @@ class Notification extends WidgetBase
}
$n = new Notification;
RPC::call('Notification.snackbar', $n->prepareSnackbar($title, $body, $picture), $time);
RPC::call('Notification.snackbar', $n->prepareSnackbar($title, $body, $picture, $action), $time);
$session->set('notifs', $notifs);
}
@ -121,13 +124,14 @@ class Notification extends WidgetBase
$session->set('notifs_key', $key);
}
function prepareSnackbar($title, $body = false, $picture = false)
function prepareSnackbar($title, $body = null, $picture = null, $action = null)
{
$view = $this->tpl();
$view->assign('title', $title);
$view->assign('body', $body);
$view->assign('picture', $picture);
$view->assign('action', $action);
return $view->draw('_notification', true);
}

View file

@ -1,11 +1,17 @@
<ul class="{if="!isset($picture)"}simple{/if}">
<li class="{if="isset($body)"}condensed{/if}">
{if="isset($picture)"}
<span class="icon bubble"><img src="{$picture}"></span>
{/if}
<span>{$title}</span>
{if="isset($body)"}
<p>{$body}</p>
{/if}
</li>
</ul>
{if="isset($action)"}
<a href="{$action}">
{/if}
<ul class="{if="!isset($picture)"}simple{/if}">
<li class="{if="isset($body)"}condensed{/if}">
{if="isset($picture)"}
<span class="icon bubble"><img src="{$picture}"></span>
{/if}
<span>{$title}</span>
{if="isset($body)"}
<p>{$body}</p>
{/if}
</li>
</ul>
{if="isset($action)"}
</a>
{/if}

View file

@ -75,6 +75,12 @@ var Notification = {
Notification_ajaxCurrent(Notification.notifs_key);
},
toast : function(html) {
// Android notification
if(typeof Android !== 'undefined') {
Android.showToast(html);
return;
}
target = document.getElementById('toast');
if(target) {
@ -88,7 +94,8 @@ var Notification = {
3000);
},
snackbar : function(html, time) {
if(Notification.inhibed == true) return;
if(typeof Android !== 'undefined'
|| Notification.inhibed == true) return;
target = document.getElementById('snackbar');
@ -102,11 +109,26 @@ var Notification = {
},
time*1000);
},
desktop : function(title, body, picture) {
desktop : function(title, body, picture, action) {
if(Notification.inhibed == true
|| Notification.focused) return;
console.log(DesktopNotification);
|| Notification.focused
|| typeof DesktopNotification === 'undefined') return;
console.log(Notification.focused);
var notification = new DesktopNotification(title, { icon: picture, body: body });
if(action !== null) {
notification.onclick = function() {
window.location.href = action;
}
}
},
android : function(title, body, picture, action) {
if(typeof Android !== 'undefined') {
Android.showNotification(title, body, picture, action);
return;
}
}
}
@ -133,6 +155,8 @@ document.onfocus = function() {
window.addEventListener('load', function () {
if(typeof DesktopNotification === 'undefined') return;
DesktopNotification.requestPermission(function (status) {
// This allows to use Notification.permission with Chrome/Safari
if(DesktopNotification.permission !== status) {

View file

@ -140,7 +140,6 @@ class Publish extends WidgetBase
RPC::call('Publish.disableSend');
if($form->title->value != '') {
$p = new PostPublish;
$p->setFrom($this->user->getLogin())
->setTo($form->to->value)
@ -148,18 +147,19 @@ class Publish extends WidgetBase
->setNode($form->node->value);
//->setLocation($geo)
//->enableComments()
if($form->content->value != '') {
$p->setContent($form->content->value);
$content = Markdown::defaultTransform($form->content->value);
$p->setContentXhtml(rawurldecode($content));
}
// Still usefull ? Check line 44
if($form->node->value == 'urn:xmpp:microblog:0') {
$p->enableComments();
}
$content = $content_xhtml = '';
if($form->content->value != '') {
$content = $form->content->value;
$content_xhtml = Markdown::defaultTransform($content);
}
if($form->embed->value != '' && filter_var($form->embed->value, FILTER_VALIDATE_URL)) {
try {
$embed = Embed\Embed::create($form->embed->value);
@ -169,13 +169,21 @@ class Publish extends WidgetBase
$key = key($embed->images);
$p->setImage($embed->images[0]['value'], $embed->title, $embed->images[0]['mime']);
} else {
$content .= $this->prepareEmbed($embed);
$content_xhtml .= $this->prepareEmbed($embed);
}
} catch(Exception $e) {
error_log($e->getMessage());
}
}
if($content != '') {
$p->setContent($content);
}
if($content_xhtml != '') {
$p->setContentXhtml(rawurldecode($content_xhtml));
}
$p->request();
} else {
RPC::call('Publish.enableSend');

View file

@ -1,13 +1,13 @@
#post_widget #enable_content > * {
form[name=post] #enable_content > * {
transition: opacity 0.3s ease;
cursor: pointer;
opacity: 0.3;
}
#post_widget #enable_content:hover > * {
form[name=post] #enable_content:hover > * {
opacity: 1;
}
#post_widget #content_field {
form[name=post] #content_field {
display: none;
}

View file

@ -243,7 +243,22 @@ class Rooms extends WidgetBase
{
$view = $this->tpl();
$cod = new \modl\ConferenceDAO();
$view->assign('conferences', $cod->getAll());
$list = $cod->getAll();
$connected = array();
foreach($list as $key => $room) {
if($this->checkConnected($room->conference, $room->nick)) {
$room->connected = true;
array_push($connected, $room);
unset($list[$key]);
}
}
$list = array_merge($connected, $list);
$view->assign('conferences', $list);
$view->assign('room', $this->get('r'));
return $view->draw('_rooms', true);

View file

@ -5,11 +5,10 @@
<span class="info">{$conferences|count}</span>
</li>
{loop="$conferences"}
{$connected = $c->checkConnected($value->conference, $value->nick)}
<li data-jid="{$value->conference}"
{if="$value->nick != null"} data-nick="{$value->nick}" {/if}
class="room {if="$connected"}online{/if}">
{if="$connected"}
class="room {if="$value->connected"}online{/if}">
{if="$value->connected"}
<span class="icon small bubble color {$value->name|stringToColor}"><i class="zmdi zmdi-accounts"></i></span>
{else}
<span class="disabled icon small bubble color {$value->name|stringToColor}"><i class="zmdi zmdi-accounts-outline"></i></span>

View file

@ -11,58 +11,123 @@ class Syndication extends WidgetBase
{
ob_clean();
if(!$this->get('f')) {
return;
}
$from = $this->get('f');
if(filter_var($from, FILTER_VALIDATE_EMAIL)) {
$node = 'urn:xmpp:microblog:0';
} else {
return;
}
$pd = new \modl\PostnDAO();
$cd = new \modl\ContactDAO();
$id = new \Modl\ItemDAO;
$this->view->assign('contact', $cd->get($from, true));
$this->view->assign('uri', Route::urlize('blog',array($from)));
if(isset($from) && isset($node)) {
$messages = $pd->getPublic($from, $node, 10, 0);
$this->view->assign('messages', $messages);
if(!$this->get('s')) {
return;
}
if(isset($messages[0])) {
header("Content-Type: application/atom+xml; charset=UTF-8");
$from = $this->get('s');
$this->view->assign('date', date('c'));
if(filter_var($from, FILTER_VALIDATE_EMAIL)) {
$node = 'urn:xmpp:microblog:0';
$contact = $cd->get($from);
} elseif(!$this->get('n')) {
return;
} else {
$node = $this->get('n');
$item = $id->getItem($from, $node);
}
}
function prepareTitle($title)
{
if($title == null)
return '...';
else
return $this->prepareContent($title, true);
}
$messages = $pd->getPublic($from, $node, 10, 0);
header("Content-Type: application/atom+xml; charset=UTF-8");
function prepareContent($content, $title = false)
{
if($title)
return cleanHTMLTags($content);
else
return trim(cleanHTMLTags(prepareString($content)));
}
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$feed = $dom->createElementNS('http://www.w3.org/2005/Atom', 'feed');
$dom->appendChild($feed);
function generateUUID($content)
{
return generateUUID(serialize($content));
}
$feed->appendChild($dom->createElement('updated', date('c')));
function prepareUpdated($date)
{
return date('c', strtotime($date));
$feed->appendChild($self = $dom->createElement('link'));
$self->setAttribute('rel', 'self');
if($contact != null) {
$feed->appendChild($dom->createElement('title', __('feed.title', $contact->getTrueName())));
$feed->appendChild($author = $dom->createElement('author'));
$author->appendChild($dom->createElement('name', $contact->getTrueName()));
$author->appendChild($dom->createElement('uri', Route::urlize('blog',array($from))));
$feed->appendChild($dom->createElement('logo', $contact->getPhoto('xl')));
$self->setAttribute('href', Route::urlize('feed',array($server)));
}
if($item != null) {
if($item->name) {
$feed->appendChild($dom->createElement('title', $item->name));
} else {
$feed->appendChild($dom->createElement('title', $item->node));
}
if($item->description) {
$feed->appendChild($dom->createElement('subtitle', $item->description));
} else {
$feed->appendChild($dom->createElement('subtitle', $item->server));
}
$self->setAttribute('href', Route::urlize('feed',array($server, $node)));
}
$feed->appendChild($generator = $dom->createElement('generator', 'Movim'));
$generator->setAttribute('uri', 'https://movim.eu');
$generator->setAttribute('version', APP_VERSION);
foreach($messages as $message) {
$feed->appendChild($entry = $dom->createElement('entry'));
if($message->title) {
$entry->appendChild($dom->createElement('title', $message->title));
} else {
$entry->appendChild($dom->createElement('title', __('post.default_title')));
}
$entry->appendChild($dom->createElement('id', $message->getUUID()));
$entry->appendChild($dom->createElement('updated', date('c', strtotime($message->updated))));
$entry->appendChild($content = $dom->createElement('content'));
$content->appendChild($div = $dom->createElementNS('http://www.w3.org/1999/xhtml', 'div'));
$content->setAttribute('type', 'xhtml');
$f = $dom->createDocumentFragment();
$f->appendXML($message->contentcleaned);
$div->appendChild($f);
//$div->appendChild($dom->createCDATASection($message->contentcleaned));
$attachements = $message->getAttachements();
if(isset($attachements['pictures'])) {
foreach($attachements['pictures'] as $value) {
$entry->appendChild($link = $dom->createElement('link'));
$link->setAttribute('rel', 'enclosure');
$link->setAttribute('type', $value['type']);
$link->setAttribute('href', $value['href']);
}
}
if(isset($attachements['files'])) {
foreach($attachements['files'] as $value) {
$entry->appendChild($link = $dom->createElement('link'));
$link->setAttribute('rel', 'enclosure');
$link->setAttribute('type', $value['type']);
$link->setAttribute('href', $value['href']);
}
}
if(isset($attachements['links'])) {
foreach($attachements['files'] as $value) {
$entry->appendChild($link = $dom->createElement('link'));
$link->setAttribute('rel', 'alternate');
$link->setAttribute('href', $value['href']);
}
}
}
echo $dom->saveXML();
exit;
}
}

View file

@ -1,43 +0,0 @@
{if="isset($contact)"}
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>{$c->__('feed.title', $contact->getTrueName())}</title>
<updated>{$date}</updated>
<author>
<name>{$contact->getTrueName()}</name>
<uri><![CDATA[{$uri}]]></uri>
</author>
{$link}
<logo>{$contact->getPhoto('xl')}</logo>
<generator uri="http://movim.eu/" version="{#APP_VERSION#}">
Movim
</generator>
<id>urn:uuid:{$uuid}</id>
{if="!empty($messages)"}
{loop="$messages"}
<entry>
<title>
{if="$value->title != null"}
<![CDATA[{$c->prepareTitle($value->title)}]]>
{else}
<![CDATA[{$c->__('post.default_title')}]]>
{/if}
</title>
<id>urn:uuid:{$c->generateUUID($value->content)}</id>
<updated>{$c->prepareUpdated($value->published)}</updated>
<content type="html">
{if="$value->contentcleaned"}
<![CDATA[{$value->contentcleaned}]]>
{else}
<![CDATA[{$value->content|html_entity_decode|prepareString}]]>
{/if}
</content>
</entry>
{/if}
{/loop}
</feed>
{else}
{$c->__('feed.nope_contact')}
{/if}

View file

@ -5,7 +5,6 @@ var Upload = {
init : function() {
document.getElementById('file').addEventListener('change', function(){
console.log(this);
var file = this.files[0];
Upload_ajaxSend({
name: file.name,

View file

@ -31,6 +31,10 @@ $parser = new \Moxl\Parser;
$buffer = '';
function handleSSLErrors($errno, $errstr) {
fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize($errstr, 'red')."\n");
}
$stdin_behaviour = function ($data) use (&$conn, $loop, &$buffer, &$connector, &$xmpp_behaviour, &$parser) {
if(substr($data, -1) == "") {
$messages = explode("", $buffer . substr($data, 0, -1));
@ -113,7 +117,16 @@ $xmpp_behaviour = function (React\Stream\Stream $stream) use (&$conn, $loop, &$s
stream_context_set_option($conn->stream, 'ssl', 'allow_self_signed', true);
#stream_context_set_option($conn->stream, 'ssl', 'verify_peer_name', false);
#stream_context_set_option($conn->stream, 'ssl', 'verify_peer', false);
set_error_handler('handleSSLErrors');
$out = stream_socket_enable_crypto($conn->stream, 1, STREAM_CRYPTO_METHOD_TLS_CLIENT);
restore_error_handler();
if($out !== true) {
$loop->stop();
return;
}
fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize('TLS enabled', 'blue')."\n");
$restart = true;
}

View file

@ -14,7 +14,7 @@ class Route extends \BaseController {
'conf' => false,
'contact' => array('f'),
'disconnect' => array('err'),
'feed' => array('f'),
'feed' => array('s', 'n'),
'grouppublic' => array('s', 'n', 'i'),
'group' => array('s', 'n', 'i'),
'help' => false,

View file

@ -226,7 +226,7 @@ ul li div.bubble {
}
ul li div.bubble div {
white-space: pre-wrap;
/*white-space: pre-wrap;*/
display: inline;
}

View file

@ -714,6 +714,19 @@ main section > div:first-child:nth-last-child(2) ~ div .actions.fixed > div:last
transform: translateX(0);
}
.snackbar > a {
pointer-events: auto;
margin: -1rem -2rem;
display: block;
margin: -2rem -1rem;
padding: 2rem 1rem;
}
.snackbar > a:hover {
border: 3px solid rgba(255, 255, 255, 0.2);
padding: calc(2rem - 3px) calc(1rem - 3px);
}
.snackbar p,
.toast p {
color: white;