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 git-2015-12-15

This commit is contained in:
Xavier ROOT 2015-12-15 11:54:49 +01:00
parent 506a3cdf95
commit c36a234b7f
977 changed files with 3500 additions and 2899 deletions

View file

@ -1,7 +1,7 @@
Movim Installation
===================
* Movim deployment tutorial: http://wiki.movim.eu/en:install
* Movim deployment tutorial: https://github.com/edhelas/movim/wiki/Install-Movim
You can also follow the Jappix project documentation for a full stack deployment:

View file

@ -7,7 +7,7 @@ Movim is a decentralized social network, written in PHP and HTML5 and based on t
Installation
------------
Please refer to the installation instructions that are available on the official Wiki : https://wiki.movim.eu .
Please refer to the installation instructions that are available on the GitHub Wiki : https://github.com/edhelas/movim/wiki .
Translations
@ -26,6 +26,12 @@ You can also use Movim on our official Pods :
* https://pod.movim.eu/ server hosted in France
* https://nl.movim.eu/ server hosted in The Netherlands
### Librairies
Movim also contains two specific librairies :
* https://github.com/edhelas/moxl Moxl (for Movim XMPP Library) is a PHP XMPP library especially made for the Movim project
* https://github.com/edhelas/modl Modl (for Movim Data Layer) is a light PHP Database layer using DAO pattern
Support Us
----------
You can support us on :

View file

@ -26,6 +26,7 @@ var MovimWebsocket = {
attached: new Array(),
registered: new Array(),
unregistered: false,
attempts: 1,
launchAttached : function() {
for(var i = 0; i < MovimWebsocket.attached.length; i++) {
@ -50,6 +51,7 @@ var MovimWebsocket = {
this.connection.onopen = function(e) {
console.log("Connection established!");
MovimWebsocket.attempts = 1;
MovimWebsocket.launchAttached();
};
@ -87,14 +89,25 @@ var MovimWebsocket = {
};
this.connection.onerror = function(e) {
console.log(e.code);
console.log(e);
console.log("Connection error!");
setTimeout(function () {
// We've tried to reconnect so increment the attempts by 1
MovimWebsocket.attempts++;
// Connection has closed so try to reconnect every 10 seconds.
MovimWebsocket.init();
}, MovimWebsocket.generateInterval());
// We prevent the onclose launch
this.onclose = null;
};
},
send : function(widget, func, params) {
if(this.connection.readyState != 0) {
if(this.connection.readyState == 1) {
this.connection.send(
JSON.stringify(
{'func' : 'message', 'body' :
@ -151,6 +164,17 @@ var MovimWebsocket = {
unregister : function(reload) {
if(reload == false) this.unregistered = true;
this.connection.unregister();
},
generateInterval :function() {
var maxInterval = (Math.pow(2, MovimWebsocket.attempts) - 1) * 1000;
if (maxInterval > 30*1000) {
maxInterval = 30*1000; // If the generated interval is more than 30 seconds, truncate it down to 30 seconds.
}
// generate the interval to a random number between 0 and the maxInterval determined from above
return Math.random() * maxInterval;
}
}
@ -164,6 +188,14 @@ function remoteUnregisterReload()
MovimWebsocket.unregister(true);
}
document.addEventListener("visibilitychange", function () {
if(!document.hidden) {
if(MovimWebsocket.connection.readyState == 3) {
MovimWebsocket.init();
}
}
});
window.onbeforeunload = function() {
MovimWebsocket.connection.onclose = function () {}; // disable onclose handler first
MovimWebsocket.connection.close()

View file

@ -0,0 +1,11 @@
<?php
class NodeController extends BaseController {
function load() {
$this->session_only = false;
}
function dispatch() {
$this->page->setTitle(__('page.groups'));
}
}

View file

@ -0,0 +1,11 @@
<?php
class TagController extends BaseController {
function load() {
$this->session_only = false;
}
function dispatch() {
$this->page->setTitle(__('page.tag'));
}
}

View file

@ -23,7 +23,7 @@ class MovimEmoji
public function replace($string, $large = false)
{
$this->_emoji->setAssetUrlFormat($this->getPath($large));
$this->_emoji->setAssetUrlFormat($this->getPath());
$string = $this->_emoji->replaceEmojiWithImages($string);
$this->_emoji->setAssetUrlFormat($this->getPath());
@ -32,10 +32,7 @@ class MovimEmoji
private function getPath($large = false)
{
$path = BASE_URI . 'themes/' . $this->_theme . '/img/emojis/';
if($large) $path .= 'large/';
return $path.'%s.png';
return BASE_URI . 'themes/' . $this->_theme . '/img/emojis/svg/%s.svg';
}
public static function getInstance()
@ -78,6 +75,18 @@ function addUrls($string, $preview = false) {
);
}
function addHFR($string) {
// HFR EasterEgg
return preg_replace_callback(
'/\[:([\w\s-]+)([:\d])*\]/', function ($match) {
$num = '';
if(count($match) == 3)
$num = $match[2].'/';
return '<img class="hfr" title="'.$match[0].'" alt="'.$match[0].'" src="http://forum-images.hardware.fr/images/perso/'.$num.$match[1].'.gif">';
}, $string
);
}
/**
* @desc Prepare the string (add the a to the links and show the smileys)
*
@ -328,7 +337,7 @@ function purifyHTML($string)
$config = \HTMLPurifier_Config::createDefault();
$config->set('HTML.Doctype', 'HTML 4.01 Transitional');
$config->set('Cache.SerializerPath', '/tmp');
$config->set('HTML.DefinitionID', 'html5-definitions');
$config->set('HTML.DefinitionID', 'html5-definitions');
$config->set('HTML.DefinitionRev', 1);
if ($def = $config->maybeGetRawHTMLDefinition()) {
$def->addElement('video', 'Block', 'Optional: (source, Flow) | (Flow, source) | Flow', 'Common', array(
@ -346,6 +355,10 @@ function purifyHTML($string)
'muted' => 'Bool',
'controls' => 'Bool',
));
$def->addElement('source', 'Block', 'Flow', 'Common', array(
'src' => 'URI',
'type' => 'Text',
));
}
$purifier = new \HTMLPurifier($config);

View file

@ -197,7 +197,7 @@ class Contact extends Model {
$p->fromBase($this->photobin);
$p->set($this->jid);
if(isset($this->email)) {
if(isset($this->email) && $this->email != '') {
\createEmailPic(strtolower($this->jid), $this->email);
}
}
@ -214,7 +214,7 @@ class Contact extends Model {
public function getPhoto($size = 'l', $jid = false) {
if($size == 'email') {
return BASE_URI.'cache/'.strtolower($this->jid).'_email.jpg';
return BASE_URI.'cache/'.strtolower($this->jid).'_email.png';
} else {
$sizes = array(
'wall' => array(1920, 1080),
@ -355,8 +355,10 @@ class Contact extends Model {
&& !filter_var($this->name, FILTER_VALIDATE_EMAIL)
)
$truename = $this->name;
else
$truename = $this->jid;
else {
$truename = explodeJid($this->jid);
$truename = $truename['username'];
}
return $truename;
}

View file

@ -412,21 +412,6 @@ class ContactDAO extends SQL {
return (int)$results[0];
}
function cleanRoster() {
$this->_sql = '
delete from rosterlink
where session = :session';
$this->prepare(
'RosterLink',
array(
'session' => $this->_user
)
);
return $this->run('RosterLink');
}
function getRoster() {
$this->_sql = '
select
@ -495,30 +480,6 @@ class ContactDAO extends SQL {
return $this->run('RosterContact');
}
function getRosterChat() {
$this->_sql = '
select * from rosterlink
left outer join (
select * from presence
order by presence.priority desc
) as presence
on rosterlink.jid = presence.jid
left outer join contact
on rosterlink.jid = contact.jid
where rosterlink.session = :session
and rosterlink.chaton > 0
order by rosterlink.groupname, rosterlink.jid, presence.value';
$this->prepare(
'RosterLink',
array(
'session' => $this->_user
)
);
return $this->run('RosterContact');
}
function getRosterFrom() {
$this->_sql = '
select * from rosterlink
@ -621,27 +582,6 @@ class ContactDAO extends SQL {
return $this->run('PresenceContact');
}
function getMe($item = false) {
$this->_sql = '
select * from contact
left outer join presence on contact.jid = presence.jid
where contact.jid = :jid
and presence.session = :session';
$this->prepare(
'RosterLink',
array(
'session' => $this->_user,
'jid' => $this->_user
)
);
if($item)
return $this->run('RosterContact');
else
return $this->run('RosterContact', 'item');
}
function getTop($limit = 6) {
$this->_sql = '
select *, jidfrom from (
@ -681,22 +621,4 @@ class ContactDAO extends SQL {
return $this->run('RosterContact');
}
function getStatistics() {
$this->_sql = '
select
(select count(*) from postn where postn.session = :session ) as post,
(select count(*) from rosterlink where rosterlink.session= :session ) as rosterlink,
(select count(*) from presence where presence.session= :session ) as presence,
(select count(*) from message where message.session = :session) as message;';
$this->prepare(
'Postn',
array(
'session' => $this->_user
)
);
return $this->run(null, 'array');
}
}

View file

@ -20,6 +20,7 @@ class Message extends Model {
public $delivered;
public $color; // Only for chatroom purpose
public $publishedPrepared; // Only for chat purpose
public function __construct()
{
@ -99,7 +100,7 @@ class Message extends Model {
public function convertEmojis()
{
$emoji = \MovimEmoji::getInstance();
$this->body = $emoji->replace($this->body);
$this->body = addHFR($emoji->replace($this->body));
}
public function addUrls()

View file

@ -2,7 +2,7 @@
namespace modl;
class MessageDAO extends SQL {
class MessageDAO extends SQL {
function set(Message $message) {
$this->_sql = '
insert into message
@ -31,7 +31,7 @@ class MessageDAO extends SQL {
:published,
:delivered
)';
$this->prepare(
'Message',
array(
@ -48,21 +48,21 @@ class MessageDAO extends SQL {
'delivered' => $message->delivered
)
);
return $this->run('Message');
}
function getContact($jid, $limitf = false, $limitr = false) {
$this->_sql = '
select * from message
select * from message
where session = :session
and (jidfrom = :jidfrom
or jidto = :jidto)
order by published desc';
if($limitr)
if($limitr)
$this->_sql = $this->_sql.' limit '.$limitr.' offset '.$limitf;
$this->prepare(
'Message',
array(
@ -71,7 +71,7 @@ class MessageDAO extends SQL {
'jidto' => $jid
)
);
return $this->run('Message');
}
@ -90,13 +90,37 @@ class MessageDAO extends SQL {
'session' => $this->_user
)
);
return $this->run('Message');
}
function getHistory($jid, $date, $limit = 30) {
$this->_sql = '
select * from message
where session = :session
and (jidfrom = :jidfrom
or jidto = :jidto)
and published < :published
order by published desc';
$this->_sql .= ' limit '.(string)$limit;
$this->prepare(
'Message',
array(
'session' => $this->_user,
'jidfrom' => $jid,
'jidto' => $jid,
'published' => $date
)
);
return $this->run('Message');
}
function getRoomSubject($room) {
$this->_sql = '
select * from message
select * from message
where jidfrom = :jidfrom
and subject != \'\'
order by published desc
@ -108,10 +132,10 @@ class MessageDAO extends SQL {
'jidfrom' => $room
)
);
return $this->run('Message', 'item');
}
function clearMessage() {
$this->_sql = '
delete from message
@ -123,24 +147,7 @@ class MessageDAO extends SQL {
'session' => $this->_user
)
);
return $this->run('Message');
}
function getStatistics() {
$this->_sql = '
select count(*) as count, extract(month from published) as month, extract(year from published) as year
from message
where session = :session
group by month, year order by year, month';
$this->prepare(
'Message',
array(
'session' => $this->_user
)
);
return $this->run(null, 'array');
}
}

View file

@ -24,7 +24,6 @@ class Postn extends Model {
public $updated; //
public $delay; //
public $tags; // Store the tags
public $picture; // Tell if the post contain embeded pictures
public $lat;
@ -36,6 +35,8 @@ class Postn extends Model {
public $hash;
private $youtube;
public function __construct() {
$this->hash = md5(openssl_random_pseudo_bytes(5));
@ -80,8 +81,6 @@ class Postn extends Model {
{"type":"text" },
"picture" :
{"type":"int", "size":4 },
"tags" :
{"type":"text" },
"hash" :
{"type":"string", "size":128 }
}';
@ -96,7 +95,7 @@ class Postn extends Model {
case 'html':
case 'xhtml':
$dom = new \DOMDocument('1.0', 'utf-8');
$import = dom_import_simplexml($c->children());
$import = @dom_import_simplexml($c->children());
if($import == null) {
$import = dom_import_simplexml($c);
}
@ -186,19 +185,24 @@ class Postn extends Model {
// Tags parsing
if($entry->entry->category) {
$this->tags = array();
$td = new \Modl\TagDAO;
if($entry->entry->category->count() == 1
&& isset($entry->entry->category->attributes()->term))
array_push($this->tags, (string)$entry->entry->category->attributes()->term);
else
foreach($entry->entry->category as $cat)
array_push($this->tags, (string)$cat->attributes()->term);
&& isset($entry->entry->category->attributes()->term)) {
$tag = new \Modl\Tag;
$tag->nodeid = $this->__get('nodeid');
$tag->tag = (string)$entry->entry->category->attributes()->term;
$td->set($tag);
} else {
foreach($entry->entry->category as $cat) {
$tag = new \Modl\Tag;
$tag->nodeid = $this->__get('nodeid');
$tag->tag = (string)$cat->attributes()->term;
$td->set($tag);
}
}
}
if(!empty($this->tags))
$this->__set('tags', serialize($this->tags));
if($contentimg != '')
$content .= '<br />'.$contentimg;
@ -206,7 +210,6 @@ class Postn extends Model {
$this->__set('commentplace', $this->origin);
$this->__set('content', trim($content));
$this->contentcleaned = purifyHTML(html_entity_decode($this->content));
if($entry->entry->geoloc) {
@ -221,6 +224,10 @@ class Postn extends Model {
return in_array($type, array('image/jpeg', 'image/png', 'image/jpg'));
}
private function typeIsLink($type) {
return $type == 'text/html';
}
private function setAttachements($links) {
$contentimg = '';
@ -252,24 +259,29 @@ class Postn extends Model {
public function getAttachements()
{
$attachements = null;
$this->picture = null;
if(isset($this->links)) {
$attachements = array('pictures' => array(), 'files' => array(), 'links' => array());
$links = unserialize($this->links);
foreach($links as $l) {
switch($l['rel']) {
case 'enclosure' :
if($this->typeIsPicture($l['type'])) {
array_push($attachements['pictures'], $l);
} else {
array_push($attachements['files'], $l);
}
break;
case 'related' :
case 'alternate' :
array_push($attachements['links'], array('href' => $l['href'], 'url' => parse_url($l['href'])));
break;
if(isset($l['type']) && $this->typeIsPicture($l['type'])) {
if($this->picture == null) {
$this->picture = $l['href'];
}
array_push($attachements['pictures'], $l);
} elseif((isset($l['type']) && $this->typeIsLink($l['type'])
|| in_array($l['rel'], array('related', 'alternate')))
&& Validator::url()->validate($l['href'])) {
if($this->youtube == null
&& preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $l['href'], $match)) {
$this->youtube = $match[1];
}
array_push($attachements['links'], array('href' => $l['href'], 'url' => parse_url($l['href'])));
} elseif(isset($l['rel']) && $l['rel'] == 'enclosure') {
array_push($attachements['files'], $l);
}
}
}
@ -284,50 +296,39 @@ class Postn extends Model {
public function getAttachement()
{
$attachements = $this->getAttachements();
if(isset($attachements['pictures'])) {
if(isset($attachements['pictures']) && !isset($attachements['links'])) {
return $attachements['pictures'][0];
}
if(isset($attachements['files'])) {
return $attachements['files'][0];
}
if(isset($attachements['links'])) {
foreach($attachements['links'] as $link) {
if(Validator::url()->validate($link['href'])) {
return $link;
}
}
return false;
return $attachements['links'][0];
}
return false;
}
public function getPicture()
{
$attachements = $this->getAttachements();
if(is_array($attachements)
&& array_key_exists('pictures', $attachements)) {
return $attachements['pictures'][0]['href'];
}
return $this->picture;
}
public function getYoutube()
{
return $this->youtube;
}
public function getPlace()
{
if(isset($this->lat, $this->lon) && $this->lat != '' && $this->lon != '') {
return true;
}
else
return false;
return (isset($this->lat, $this->lon) && $this->lat != '' && $this->lon != '');
}
public function isMine()
{
$user = new \User();
if($this->aid == $user->getLogin()
|| $this->origin == $user->getLogin())
return true;
else
return false;
return ($this->aid == $user->getLogin()
|| $this->origin == $user->getLogin());
}
public function getUUID()
@ -341,11 +342,7 @@ class Postn extends Model {
public function isMicroblog()
{
if($this->node == "urn:xmpp:microblog:0") {
return true;
} else {
return false;
}
return ($this->node == "urn:xmpp:microblog:0");
}
public function isEditable()
@ -355,7 +352,7 @@ class Postn extends Model {
public function isShort()
{
return (strlen($this->contentcleaned) < 500);
return (strlen($this->contentcleaned) < 700);
}
public function getPublicUrl()
@ -363,15 +360,29 @@ class Postn extends Model {
if($this->isMicroblog()) {
return \Route::urlize('blog', array($this->origin));
} else {
return \Route::urlize('grouppublic', array($this->origin, $this->node));
return \Route::urlize('node', array($this->origin, $this->node));
}
}
public function getTags()
{
$td = new \Modl\TagDAO;
$tags = $td->getTags($this->nodeid);
if(is_array($tags)) {
return array_map(function($tag) { return $tag->tag; }, $tags);
}
}
public function getTagsImploded()
{
$tags = $this->getTags();
if(is_array($tags)) {
return implode(', ', $tags);
}
}
public function isPublic() {
if(isset($this->privacy) && $this->privacy) {
return true;
}
return false;
return (isset($this->privacy) && $this->privacy);
}
}

View file

@ -26,7 +26,6 @@ class PostnDAO extends SQL {
links = :links,
picture = :picture,
tags = :tags,
hash = :hash
@ -57,7 +56,6 @@ class PostnDAO extends SQL {
'links' => $post->links,
'picture' => $post->picture,
'tags' => $post->tags,
'hash' => $post->hash,
@ -97,7 +95,6 @@ class PostnDAO extends SQL {
links,
picture,
tags,
hash)
values(
@ -125,7 +122,6 @@ class PostnDAO extends SQL {
:links,
:picture,
:tags,
:hash
)';
@ -153,7 +149,6 @@ class PostnDAO extends SQL {
'links' => $post->links,
'picture' => $post->picture,
'tags' => $post->tags,
'hash' => $post->hash,
@ -210,8 +205,8 @@ class PostnDAO extends SQL {
and postn.node != \'urn:xmpp:microblog:0\'
order by postn.published desc';
if($limitr)
$this->_sql = $this->_sql.' limit '.$limitr.' offset '.$limitf;
if($limitr !== false)
$this->_sql = $this->_sql.' limit '.(int)$limitr.' offset '.(int)$limitf;
$this->prepare(
'Postn',
@ -225,6 +220,28 @@ class PostnDAO extends SQL {
return $this->run('ContactPostn');
}
function getPublicTag($tag, $limitf = false, $limitr = false) {
$this->_sql = '
select *, postn.aid, privacy.value as privacy from postn
left outer join contact on postn.aid = contact.jid
left outer join privacy on postn.nodeid = privacy.pkey
where nodeid in (select nodeid from tag where tag = :title)
and privacy.value = 1
order by postn.published desc';
if($limitr !== false)
$this->_sql = $this->_sql.' limit '.(int)$limitr.' offset '.(int)$limitf;
$this->prepare(
'Postn',
array(
'title' => $tag # Hack
)
);
return $this->run('ContactPostn');
}
function getNodeUnfiltered($from, $node, $limitf = false, $limitr = false) {
$this->_sql = '
select *, postn.aid, privacy.value as privacy from postn
@ -248,20 +265,21 @@ class PostnDAO extends SQL {
return $this->run('ContactPostn');
}
function getGallery($from) {
function getGallery($from, $limitf = false, $limitr = false) {
$this->_sql = '
select *, postn.aid, privacy.value as privacy from postn
left outer join contact on postn.aid = contact.jid
left outer join privacy on postn.nodeid = privacy.pkey
where (postn.origin in (select jid from rosterlink where session = :origin and rostersubscription in (\'both\', \'to\')))
and postn.origin = :aid
where postn.aid = :aid
and postn.picture = 1
order by postn.published desc';
if($limitr !== false)
$this->_sql = $this->_sql.' limit '.(int)$limitr.' offset '.(int)$limitf;
$this->prepare(
'Postn',
array(
'origin' => $this->_user,
'aid' => $from // Another hack
)
);
@ -410,7 +428,7 @@ class PostnDAO extends SQL {
return $this->run('ContactPostn');
}
function getPublicItem($origin, $node, $nodeid, $limitf = false, $limitr = false) {
function getPublicItem($origin, $node, $nodeid) {
$this->_sql = '
select *, postn.aid, privacy.value as privacy from postn
left outer join contact on postn.aid = contact.jid
@ -421,9 +439,6 @@ class PostnDAO extends SQL {
and postn.nodeid = :nodeid
order by postn.published desc';
if($limitr)
$this->_sql = $this->_sql.' limit '.$limitr.' offset '.$limitf;
$this->prepare(
'Postn',
array(
@ -483,24 +498,6 @@ class PostnDAO extends SQL {
return $this->run('Postn');
}
// TODO: fixme
function getStatistics() {
$this->_sql = '
select count(*) as count, extract(month from published) as month, extract(year from published) as year
from postn
where session = :session
group by month, year order by year desc, month desc';
$this->prepare(
'Postn',
array(
'session' => $this->_user
)
);
return $this->run(null, 'array');
}
function getCountSince($date) {
$this->_sql = '
select count(*) from postn

View file

@ -137,25 +137,6 @@ class RosterLinkDAO extends SQL {
$this->set($r);
}
function setChat($jid, $chaton) {
$this->_sql = '
update rosterlink
set chaton = :chaton
where session = :session
and jid = :jid';
$this->prepare(
'RosterLink',
array(
'session' => $this->_user,
'jid' => $jid,
'chaton' => $chaton
)
);
return $this->run('RosterLink');
}
function get($jid) {
$this->_sql = '
select *
@ -223,23 +204,6 @@ class RosterLinkDAO extends SQL {
return $this->run('RosterLink');
}
function getChats() {
$this->_sql = '
select *
from rosterlink
where session=:session
and chaton > 0';
$this->prepare(
'RosterLink',
array(
'session' => $this->_user
)
);
return $this->run('RosterLink');
}
function clearRosterLink() {
$this->_sql = '
delete from rosterlink

View file

@ -0,0 +1,20 @@
<?php
namespace modl;
class Tag extends Model {
public $tag;
public $nodeid;
public function __construct() {
$this->_struct = '
{
"tag" :
{"type":"string", "size":64, "mandatory":true, "key":true },
"nodeid" :
{"type":"string", "size":96, "mandatory":true, "key":true }
}';
parent::__construct();
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace modl;
class TagDAO extends SQL {
function set(Tag $t) {
$this->_sql = '
update tag
set nodeid = :nodeid,
tag = :tag
where nodeid = :nodeid
and tag = :tag';
$this->prepare(
'Tag',
array(
'nodeid' => $t->nodeid,
'tag' => $t->tag
)
);
$this->run('Tag');
if(!$this->_effective) {
$this->_sql = '
insert into tag
(nodeid, tag)
values (:nodeid, :tag)';
$this->prepare(
'Tag',
array(
'nodeid' => $t->nodeid,
'tag' => $t->tag
)
);
$this->run('Tag');
}
}
function getTags($nodeid) {
$this->_sql = '
select * from tag
where nodeid = :nodeid';
$this->prepare(
'Tag',
array(
'nodeid' => $nodeid
)
);
return $this->run('Tag');
}
}

View file

@ -0,0 +1,7 @@
<main>
<section>
<div style="background-color: #EEE;">
<?php $this->widget('Blog');?>
</div>
</section>
</main>

View file

@ -1,26 +1,19 @@
<?php /* -*- mode: html -*- */
$cd = new \Modl\ConfigDAO();
$config = $cd->get();
?><!DOCTYPE html>
<!DOCTYPE html>
<html ng-app="roster">
<head>
<meta charset="utf-8" />
<title><?php $this->title();?></title>
<meta name="description" content="<?php echo $config->description; ?>" />
<meta name="theme-color" content="#1C1D5B" />
<link rel="shortcut icon" href="<?php $this->linkFile('img/favicon.ico');?>" />
<!--<link rel="stylesheet" href="<?php echo BASE_URI; ?>app/assets/js/leaflet.css" />
<script src="<?php echo BASE_URI; ?>app/assets/js/leaflet.js"></script>-->
<script src="<?php echo BASE_URI; ?>app/assets/js/favico.js"></script>
<?php $this->meta();?>
<!-- OTR -->
<!--<script src="<?php echo BASE_URI; ?>app/assets/js/otr/dep/bigint.js"></script>
<script src="<?php echo BASE_URI; ?>app/assets/js/otr/dep/crypto.js"></script>
<script src="<?php echo BASE_URI; ?>app/assets/js/otr/dep/eventemitter.js"></script>
<script src="<?php echo BASE_URI; ?>app/assets/js/otr/otr.js"></script>
<script src="<?php echo BASE_URI; ?>app/assets/js/cycle.js"></script>-->
<meta name="application-name" content="Movim">
<link rel="shortcut icon" href="<?php $this->linkFile('img/favicon.ico');?>" />
<link rel="icon" type="image/png" href="<?php $this->linkFile('img/app/48.png');?>" sizes="48x48">
<link rel="icon" type="image/png" href="<?php $this->linkFile('img/app/96.png');?>" sizes="96x96">
<link rel="icon" type="image/png" href="<?php $this->linkFile('img/app/128.png');?>" sizes="128x128">
<script src="<?php echo BASE_URI; ?>app/assets/js/favico.js"></script>
<meta name="viewport" content="width=device-width, user-scalable=no">
@ -55,10 +48,6 @@
<?php $this->widget('Dialog');?>
<?php $this->widget('Notification');?>
<?php $this->content();?>
<?php
$this->displayFooterDebug();
?>
<script type="text/javascript">movim_onload();</script>
</body>
</html>

View file

@ -0,0 +1,7 @@
<main>
<section>
<div style="background-color: #EEE;">
<?php $this->widget('Blog');?>
</div>
</section>
</main>

View file

@ -56,7 +56,7 @@ class Account extends WidgetBase
function ajaxChangePassword($form)
{
$validate = Validator::string()->length(6, 40);
$validate = Validator::stringType()->length(6, 40);
$p1 = $form->password->value;
$p2 = $form->password_confirmation->value;
@ -113,7 +113,7 @@ class Account extends WidgetBase
private function validateServer($server)
{
$validate_server = Validator::string()->noWhitespace()->length(6, 80);
$validate_server = Validator::stringType()->noWhitespace()->length(6, 80);
if(!$validate_server->validate($server)) return false;
else return true;
}

View file

@ -1,7 +1,6 @@
<?php
use Moxl\Xec\Action\Disco\Request;
use Moxl\Xec\Action\Register\Get;
use Moxl\Xec\Action\Register\Set;
class AccountNext extends WidgetBase {
@ -30,32 +29,40 @@ class AccountNext extends WidgetBase {
{
$form = $package->content;
$xtf = new \XMPPtoForm();
if(!empty($form->x)){
switch($form->x->attributes()->xmlns) {
case 'jabber:x:data' :
$formview = $this->tpl();
if($package->from == 'movim.eu') {
$movimview = $this->tpl();
$movimview->assign('submitdata', $this->call('ajaxRegister', "movim_form_to_json('data')"));
$html = $movimview->draw('_accountnext_movim', true);
$formh = $xtf->getHTML($form->x->asXML());
$formview->assign('submitdata', $this->call('ajaxRegister', "movim_form_to_json('data')"));
RPC::call('movim_fill', 'subscription_form', $html);
} else {
$xtf = new \XMPPtoForm();
if(!empty($form->x)){
switch($form->x->attributes()->xmlns) {
case 'jabber:x:data' :
$formview = $this->tpl();
$formview->assign('formh', $formh);
$html = $formview->draw('_accountnext_form', true);
$formh = $xtf->getHTML($form->x->asXML());
$formview->assign('submitdata', $this->call('ajaxRegister', "movim_form_to_json('data')"));
RPC::call('movim_fill', 'subscription_form', $html);
break;
case 'jabber:x:oob' :
$oobview = $this->tpl();
$oobview->assign('url', (string)$form->x->url);
$formview->assign('formh', $formh);
$html = $formview->draw('_accountnext_form', true);
$html = $oobview->draw('_accountnext_oob', true);
RPC::call('movim_fill', 'subscription_form', $html);
break;
case 'jabber:x:oob' :
$oobview = $this->tpl();
$oobview->assign('url', (string)$form->x->url);
RPC::call('movim_fill', 'subscription_form', $html);
break;
$html = $oobview->draw('_accountnext_oob', true);
RPC::call('movim_fill', 'subscription_form', $html);
break;
}
} else{
$formh = $xtf->getHTML($form->asXML());
}
} else{
$formh = $xtf->getHTML($form->asXML());
}
}
@ -68,7 +75,7 @@ class AccountNext extends WidgetBase {
$html = $view->draw('_accountnext_registered', true);
RPC::call('movim_fill', 'subscription_form', $html);
RPC::call('movim_fill', 'subscribe', $html);
RPC::call('setUsername', $data->username->value);
}
@ -103,6 +110,12 @@ class AccountNext extends WidgetBase {
function ajaxRegister($form)
{
if(isset($form->re_password)
&& $form->re_password->value != $form->password->value) {
Notification::append(null, $this->__('account.password_not_same'));
return;
}
$s = new Set;
$s->setData($form)->request();
}

View file

@ -1,8 +1,7 @@
<br />
<form name="data">
{$formh}
<a
class="button color green oppose"
class="button color green oppose"
onclick="{$submitdata}"
>
{$c->__('button.validate')}

View file

@ -0,0 +1,20 @@
<form name="data">
<div id="movim">
<span>@movim.eu</span>
<label for="username">{$c->__('input.username')}</label>
<input name="username" type="text" placeholder="username">
</div>
<div>
<label for="password">{$c->__('input.password')}</label>
<input name="password" type="password" placeholder="{$c->__('input.password')}">
</div>
<div class="compact">
<input name="re_password" type="password" placeholder="{$c->__('credentials.re_password')}">
</div>
<a
class="button color green oppose"
onclick="{$submitdata}"
>
{$c->__('button.validate')}
</a>
</form>

View file

@ -1,4 +1,4 @@
<ul class="thick">
<ul id="obb" class="thick">
<li class="condensed">
<span class="icon bubble color blue">
<i class="zmdi zmdi-chevron-right"></i>

View file

@ -1,3 +1,30 @@
#subscription_form form > div {
left: 2rem;
left: 1rem;
}
#subscription_form form {
padding-top: 5rem;
}
#subscription_form ul#obb {
padding-top: 10rem;
}
#subscription_form div#movim input {
width: calc(100% - 15rem);
text-align: right;
}
#subscription_form div#movim span {
color: gray;
font-weight: bold;
text-align: left;
font-size: 2rem;
top: 4rem;
float: right;
position: relative;
line-height: 3rem;
padding: 1rem;
width: 15rem;
box-sizing: border-box;
}

View file

@ -1,11 +1,20 @@
<div id="subscribe">
<div id="subscription_form" class="padded_right">
<ul class="simple thick">
<li>
<span>{$c->__('create.title')} {$c->__('create.server_on')} {$host}</span>
<p>{$c->__('create.loading')}</p>
</li>
</ul>
<div class="flex">
<div class="block on_desktop">
<div class="placeholder icon account">
<h4>{$c->__('create.title')}</h4>
<h4>{$c->__('create.placeholder')}</h4>
</div>
</div>
<div id="subscription_form" class="block">
<ul class="simple thick">
<li>
<span>{$c->__('create.title')} {$c->__('create.server_on')} {$host}</span>
<p>{$c->__('create.loading')}</p>
</li>
</ul>
</div>
</div>
<script type="text/javascript">
MovimWebsocket.attach(function()

View file

@ -4,6 +4,7 @@ notfound = No account creation form found on the server
server_on = on
successfull = Your acccount has been successfully registered
loading = Loading
placeholder = …and start playing
[error]
not_acceptable = Not Acceptable

View file

@ -6,7 +6,19 @@
<div id="preview" class="block">
<div>
<form name="avatarform" id="avatarform">
<img src="data:image/jpeg;base64,{$photobin}">
{if="isset($photobin) && $photobin != ''"}
<img src="data:image/jpeg;base64,{$photobin}">
{else}
<img src="#" class="error">
<ul class="thick">
<li>
<span class="icon bubble color {$me->jid|stringToColor}">
<i class="zmdi zmdi-account"></i>
</span>
<p>{$c->__('avatar.missing')}</p>
</li>
</ul>
{/if}
<input type="hidden" name="photobin" value="{$photobin}"/>
</form>
</div>
@ -40,7 +52,7 @@
</div>
</div>
<!--
<div class="block">
<div class="block">
<input type="file" onchange="vCardImageLoad(this.files);">
<label for="avatar">{$c->__('page.avatar')}</label>
<input type="hidden" name="photobin" value="{$photobin}"/>
@ -62,16 +74,16 @@
<div id="camdiv" class="block">
<video id="runningcam" class="squares" autoplay></video>
<canvas style="display:none;"></canvas>
<a
id="shoot"
class="button flat oppose"
<a
id="shoot"
class="button flat oppose"
onclick="return false;">
{$c->__('avatar.cheese')}
</a>
<a
id="capture"
class="button flat"
id="capture"
class="button flat"
onclick="
showVideo();
return false;">
@ -85,8 +97,8 @@
onclick="
{$submit}
movim_button_save('#avatarvalidate');
this.value = '{$c->__('button.submitting')}';
this.className='button inactive oppose';"
this.value = '{$c->__('button.submitting')}';
this.className='button inactive oppose';"
class="button color oppose"
id="avatarvalidate"
>{$c->__('button.submit')}</a>

View file

@ -14,3 +14,7 @@
border-radius: 0.25rem;
margin: 0 auto;
}
#avatar_form div#preview img.error {
display: none;
}

View file

@ -34,7 +34,14 @@ var Avatar = {
var base64 = canvas.toDataURL('image/jpeg', 0.7);
var preview = document.querySelector('form[name=avatarform] img');
var list = document.querySelector('form[name=avatarform] ul');
if(list) list.style.display = 'none';
var input = document.querySelector('input[name="photobin"]');
if(preview.className == 'error') preview.className = '';
preview.src = base64;
var bin = base64.split(",");
@ -48,8 +55,8 @@ MovimWebsocket.attach(function() {
});
function showVideo(){
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
navigator.getUserMedia({video:true, audio:false}, successCallback, errorCallback);
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
navigator.getUserMedia({video:true, audio:false}, successCallback, errorCallback);
movim_toggle_class('#camdiv', 'active');
}

View file

@ -6,3 +6,4 @@ cheese = Cheese !
snapshot = Take a webcam snapshot
updated = Avatar Updated
not_updated = Avatar Not Updated
missing = No avatar defined yet

View file

@ -2,68 +2,132 @@
use Respect\Validation\Validator;
include_once WIDGETS_PATH.'Post/Post.php';
class Blog extends WidgetBase {
public $_paging = 10;
private $_from;
private $_node;
private $_item;
private $_id;
private $_contact;
private $_messages;
private $_page;
private $_mode;
private $_tag;
function load()
{
if($this->_view == 'node') {
$this->_from = $this->get('s');
$this->_node = $this->get('n');
if(!$this->validateServerNode($this->_from, $this->_node)) return;
$pd = new \Modl\ItemDAO;
$this->_item = $pd->getItem($this->_from, $this->_node);
$this->_mode = 'group';
$this->url = Route::urlize('node', array($this->_from, $this->_node));
} elseif($this->_view == 'tag' && $this->validateTag($this->get('t'))) {
$this->_mode = 'tag';
$this->_tag = $this->get('t');
$this->title = '#'.$this->_tag;
} else {
$this->_from = $this->get('f');
$cd = new \modl\ContactDAO();
$this->_contact = $cd->get($this->_from, true);
if(filter_var($this->_from, FILTER_VALIDATE_EMAIL)) {
$this->_node = 'urn:xmpp:microblog:0';
} else {
return;
}
$this->_mode = 'blog';
$this->url = Route::urlize('blog', $this->_from);
}
$pd = new \modl\PostnDAO();
if($this->_id = $this->get('i')) {
if(Validator::intType()->between(0, 100)->validate($this->_id)) {
if(isset($this->_tag)) {
$this->_messages = $pd->getPublicTag($this->get('t'), $this->_id * $this->_paging, $this->_paging + 1);
} else {
$this->_messages = $pd->getNodeUnfiltered($this->_from, $this->_node, $this->_id * $this->_paging, $this->_paging + 1);
}
$this->_page = $this->_id + 1;
} elseif(Validator::stringType()->length(5, 100)->validate($this->_id)) {
$this->_messages = $pd->getPublicItem($this->_from, $this->_node, $this->_id);
if(is_object($this->_messages[0])) {
$this->title = $this->_messages[0]->title;
$description = stripTags($this->_messages[0]->contentcleaned);
if(!empty($description)) {
$this->description = $description;
}
$attachements = $this->_messages[0]->getAttachements();
if($attachements && array_key_exists('pictures', $attachements)) {
$this->image = urldecode($attachements['pictures'][0]['href']);
}
}
if($this->_view == 'node') {
$this->url = Route::urlize('node', array($this->_from, $this->_node, $this->_id));
} else {
$this->url = Route::urlize('blog', array($this->_from, $this->_id));
}
}
} else {
$this->_page = 1;
if(isset($this->_tag)) {
$this->_messages = $pd->getPublicTag($this->get('t'), 0, $this->_paging + 1);
} else {
$this->_messages = $pd->getNodeUnfiltered($this->_from, $this->_node, 0, $this->_paging + 1);
}
}
if(count($this->_messages) == $this->_paging + 1) {
array_pop($this->_messages);
}
$this->user = new User($this->_from);
$cssurl = $this->user->getDumpedConfig('cssurl');
if(isset($cssurl)
&& $cssurl != ''
&& Validator::url()->validate($cssurl)) {
$this->addrawcss($cssurl);
}
}
public function preparePost($p) {
$pw = new Post;
return $pw->preparePost($p, true, true);
}
function display()
{
if($this->_view == 'grouppublic') {
$from = $this->get('s');
$node = $this->get('n');
$this->view->assign('server', $this->_from);
$this->view->assign('node', $this->_node);
if(!$this->validateServerNode($from, $node)) return;
$this->view->assign('item', $this->_item);
$this->view->assign('contact', $this->_contact);
$this->view->assign('mode', $this->_mode);
$this->view->assign('more', $this->_page);
$this->view->assign('posts', $this->_messages);
$this->view->assign('mode', 'group');
$this->view->assign('server', $from);
$this->view->assign('node', $node);
$pd = new \Modl\ItemDAO;
$this->view->assign('item', $pd->getItem($from, $node));
} else {
$from = $this->get('f');
$cd = new \modl\ContactDAO();
$c = $cd->get($from, true);
$this->view->assign('contact', $c);
if(filter_var($from, FILTER_VALIDATE_EMAIL)) {
$node = 'urn:xmpp:microblog:0';
} else {
return;
}
$this->view->assign('mode', 'blog');
}
$pd = new \modl\PostnDAO();
if($id = $this->get('i')) {
if(Validator::int()->between(0, 100)->validate($id)) {
$messages = $pd->getNodeUnfiltered($from, $node, $id * $this->_paging, $this->_paging + 1);
$page = $id + 1;
} elseif(Validator::string()->length(5, 100)->validate($id)) {
$messages = $pd->getPublicItem($from, $node, $id);
}
} else {
$page = 1;
$messages = $pd->getNodeUnfiltered($from, $node, 0, $this->_paging + 1);
}
if(count($messages) == $this->_paging + 1) {
array_pop($messages);
$this->view->assign('more', $page);
}
$this->view->assign('posts', $messages);
$this->view->assign('tag', $this->_tag);
}
private function validateServerNode($server, $node)
{
$validate_server = Validator::string()->noWhitespace()->length(6, 40);
$validate_node = Validator::string()->length(3, 100);
$validate_server = Validator::stringType()->noWhitespace()->length(6, 40);
$validate_node = Validator::stringType()->length(3, 100);
if(!$validate_server->validate($server)
|| !$validate_node->validate($node)
@ -71,6 +135,11 @@ class Blog extends WidgetBase {
else return true;
}
private function validateTag($tag)
{
return Validator::stringType()->notEmpty()->alnum()->validate($tag);
}
function getComments($post)
{
$pd = new \Modl\PostnDAO();

View file

@ -31,6 +31,17 @@
<p>{$contact->description}</p>
{/if}
</li>
{elseif="$mode == 'tag'"}
<li class="condensed">
<span class="icon gray">
<i class="zmdi zmdi-tag"></i>
</span>
<h2>
<a href="{$c->route('tag', array($tag))}">
#{$tag}
</a>
</h2>
</li>
{else}
<li class="condensed action">
<div class="action">
@ -45,7 +56,7 @@
<i class="zmdi zmdi-pages"></i>
</span>
<h2>
<a href="{$c->route('group', array($server, $node))}">
<a href="{$c->route('node', array($server, $node))}">
{if="$item != null"}
{if="$item->name"}
{$item->name}
@ -67,149 +78,7 @@
</ul>
{loop="$posts"}
<article class="block">
<header>
<ul class="thick">
<li class="condensed">
{$url = $value->getContact()->getPhoto('s')}
{if="$url"}
<span class="icon bubble">
<img src="{$url}">
</span>
{else}
<span class="icon bubble color {$value->getContact()->jid|stringToColor}">
<i class="zmdi zmdi-account"></i>
</span>
{/if}
<h2>
<a href="
{if="$value->isMicroblog()"}
{$c->route('blog', array($value->origin, $value->nodeid))}
{else}
{$c->route('group', array($value->origin, $value->node, $value->nodeid))}
{/if}
">
{if="$value->title != null"}
{$value->title}
{else}
{$c->__('post.default_title')}
{/if}
</a>
</h2>
<p>
{if="$value->getContact()->getTrueName() != '' && $value->privacy"}
<i class="zmdi zmdi-account"></i> {$value->getContact()->getTrueName()}
{/if}
{$value->published|strtotime|prepareDate}
</p>
</li>
</ul>
</header>
{if="!$value->isPublic()"}
<ul class="thick">
<li>
<span class="icon color gray bubble">
<i class="zmdi zmdi-lock"></i>
</span>
<p class="center"> {$c->__('blog.private')} - <a href="{$c->route('main')}">{$c->__('page.login')}</a></p>
</li>
</ul>
<br />
{else}
{$attachements = $value->getAttachements()}
<section>
<content>
{if="strlen($value->contentcleaned) < 500 && isset($attachements.pictures)"}
{loop="$attachements.pictures"}
<a href="{$value.href}" class="alternate" target="_blank">
<img class="big_picture" type="{$value.type}" src="{$value.href|urldecode}"/>
</a>
{/loop}
{/if}
{$value->contentcleaned}
</content>
</section>
<footer>
<ul class="middle divided spaced">
{if="isset($attachements.links)"}
{loop="$attachements.links"}
{if="substr($value.href, 0, 5) != 'xmpp:' && filter_var($value.href, FILTER_VALIDATE_URL)"}
<li>
<span class="icon">
<img src="http://icons.duckduckgo.com/ip2/{$value.url.host}.ico"/>
</span>
<a href="{$value.href}" class="alternate" target="_blank">
<span>{$value.href|urldecode}</span>
</a>
</li>
{/if}
{/loop}
{/if}
{if="isset($attachements.files)"}
{loop="$attachements.files"}
<li>
<a
href="{$value.href}"
class="enclosure"
type="{$value.type}"
target="_blank">
<span class="icon gray">
<span class="zmdi zmdi-attachment-alt"></span>
</span>
<span>{$value.href|urldecode}</span>
</a>
</li>
{/loop}
{/if}
</ul>
{if="strlen($value->contentcleaned) >= 500 && isset($attachements.pictures)"}
<ul class="flex middle">
{loop="$attachements.pictures"}
<li class="block pic">
<span class="icon gray">
<i class="zmdi zmdi-image"></i>
</span>
<a href="{$value.href}" class="alternate" target="_blank">
<img type="{$value.type}" src="{$value.href|urldecode}"/>
</a>
</li>
{/loop}
</ul>
{/if}
</footer>
{$comments = $c->getComments($value)}
{if="$comments"}
<ul class="spaced middle">
<li class="subheader">
{$c->__('post.comments')}
<span class="info">{$comments|count}</span>
</li>
{loop="$comments"}
<li class="condensed">
{$url = $value->getContact()->getPhoto('s')}
{if="$url"}
<span class="icon bubble">
<img src="{$url}">
</span>
{else}
<span class="icon bubble color {$value->getContact()->jid|stringToColor}">
<i class="zmdi zmdi-account"></i>
</span>
{/if}
<span class="info">{$value->published|strtotime|prepareDate}</span>
<span>
{$value->getContact()->getTrueName()}
</span>
<p class="all">
{$value->contentraw}
</p>
</li>
{/loop}
</ul>
{/if}
<br />
{/if}
</article>
{$c->preparePost($value)}
{/loop}
{if="isset($more)"}
<article>

View file

@ -25,7 +25,7 @@ use Moxl\Xec\Action\Presence\Muc;
class Bookmark extends WidgetBase
{
private $_list_server;
function load()
{
$this->addcss('bookmark.css');
@ -35,19 +35,19 @@ class Bookmark extends WidgetBase
}
function display()
{
{
$this->view->assign('subscriptionconfig', Route::urlize('conf', false, 'groupsubscribedlistconfig'));
$this->view->assign('getbookmark', $this->call("ajaxGetBookmark"));
$this->view->assign('setbookmark', $this->call("ajaxSetBookmark", "''"));
$this->view->assign('preparebookmark', $this->prepareBookmark());
}
function prepareBookmark() {
$cd = new \modl\ConferenceDAO();
$sd = new \modl\SubscriptionDAO();
// The URL add form
$listview = $this->tpl();
$listview->assign('conferences', $cd->getAll());
@ -58,19 +58,19 @@ class Bookmark extends WidgetBase
// The URL add form
$urlview = $this->tpl();
$urlview->assign(
'submit',
'submit',
$this->call(
'ajaxBookmarkUrlAdd',
'ajaxBookmarkUrlAdd',
"movim_parse_form('bookmarkurladd')")
);
$html .= $urlview->draw('_bookmark_url_add', true);
// The MUC add form
$mucview = $this->tpl();
$mucview->assign(
'submit',
'submit',
$this->call(
'ajaxBookmarkMucAdd',
'ajaxBookmarkMucAdd',
"movim_parse_form('bookmarkmucadd')")
);
$html .= $mucview->draw('_bookmark_muc_add', true);
@ -81,7 +81,7 @@ class Bookmark extends WidgetBase
function checkNewServer($node) {
$r = false;
if($this->_list_server != $node->server)
$r = true;
@ -95,7 +95,7 @@ class Bookmark extends WidgetBase
"'".$node->conference."'"
);
}
function getMucJoin($node) {
return $this->call(
'ajaxBookmarkMucJoin',
@ -103,43 +103,43 @@ class Bookmark extends WidgetBase
"'".$node->nick."'"
);
}
function onGroupSubscribed()
{
$html = $this->prepareBookmark();
RPC::call('movim_fill', 'bookmarks', $html);
RPC::call('setBookmark');
$html = $this->prepareBookmark();
RPC::call('movim_fill', 'bookmarks', $html);
RPC::call('setBookmark');
}
function onGroupUnsubscribed()
{
$html = $this->prepareBookmark();
RPC::call('movim_fill', 'bookmarks', $html);
RPC::call('setBookmark');
$html = $this->prepareBookmark();
RPC::call('movim_fill', 'bookmarks', $html);
RPC::call('setBookmark');
}
function onBookmark()
{
$html = $this->prepareBookmark();
RPC::call('movim_fill', 'bookmarks', $html);
Notification::append(null, $this->__('bookmarks.updated'));
}
function ajaxGetBookmark()
function ajaxGetBookmark()
{
$b = new Get;
$b->setTo($this->user->getLogin())
->request();
}
function ajaxSetBookmark($item = false)
function ajaxSetBookmark($item = false)
{
$arr = array();
if($item) {
array_push($arr, $item);
}
$sd = new \modl\SubscriptionDAO();
$cd = new \modl\ConferenceDAO();
@ -151,7 +151,7 @@ class Bookmark extends WidgetBase
'title' => $s->title,
'subid' => $s->subid,
'tags' => unserialize($s->tags),
'node' => $s->node));
'node' => $s->node));
}
foreach($cd->getAll() as $c) {
@ -161,18 +161,18 @@ class Bookmark extends WidgetBase
'name' => $c->name,
'autojoin' => $c->autojoin,
'nick' => $c->nick,
'jid' => $c->conference));
'jid' => $c->conference));
}
$b = new Set;
$b->setArr($arr)
->setTo($this->user->getLogin())
->request();
}
// Add a new MUC
function ajaxBookmarkMucAdd($form)
function ajaxBookmarkMucAdd($form)
{
if(!filter_var($form['jid'], FILTER_VALIDATE_EMAIL)) {
$html = '<div class="message error">'.$this->__('chatroom.bad_id').'</div>' ;
@ -181,28 +181,28 @@ class Bookmark extends WidgetBase
} elseif(trim($form['name']) == '') {
$html = '<div class="message error">'.$this->__('chatroom.empty_name').'</div>' ;
RPC::call('movim_fill', 'bookmarkmucadderror', $html);
RPC::commit();
RPC::commit();
} else {
$item = array(
'type' => 'conference',
'name' => $form['name'],
'autojoin' => $form['autojoin'],
'nick' => $form['nick'],
'jid' => $form['jid']);
'jid' => $form['jid']);
$this->ajaxSetBookmark($item);
}
}
// Remove a MUC
function ajaxBookmarkMucRemove($jid)
{
$cd = new \modl\ConferenceDAO();
$cd->deleteNode($jid);
$this->ajaxSetBookmark();
}
// Join a MUC
// Join a MUC
function ajaxBookmarkMucJoin($jid, $nickname)
{
$p = new Muc;
@ -212,7 +212,7 @@ class Bookmark extends WidgetBase
}
/*
// Add a new URL
function ajaxBookmarkUrlAdd($form)
function ajaxBookmarkUrlAdd($form)
{
if(!filter_var($form['url'], FILTER_VALIDATE_URL)) {
$html = '<div class="message error">'.t('Bad URL').'</div>' ;
@ -221,24 +221,24 @@ class Bookmark extends WidgetBase
} elseif(trim($form['name']) == '') {
$html = '<div class="message error">'.t('Empty name').'</div>' ;
RPC::call('movim_fill', 'bookmarkadderror', $html);
RPC::commit();
RPC::commit();
} else {
$bookmarks = Cache::c('bookmark');
$bookmarks = Cache::c('bookmark');
if($bookmarks == null)
$bookmarks = array();
array_push($bookmarks,
array(
'type' => 'url',
'name' => $form['name'],
'url' => $form['url']));
'url' => $form['url']));
$this->ajaxSetBookmark($bookmarks);
}
}
// Remove an URL
function ajaxBookmarkUrlRemove($url)
{

View file

@ -12,6 +12,8 @@ use Respect\Validation\Validator;
class Chat extends WidgetBase
{
private $_pagination = 30;
function load()
{
$this->addjs('chat.js');
@ -314,6 +316,30 @@ class Chat extends WidgetBase
$mp->setTo($to)->request();
}
/**
* @brief Get the chat history
*
* @param string jid
* @param string time
*/
function ajaxGetHistory($jid, $date)
{
if(!$this->validateJid($jid)) return;
$md = new \Modl\MessageDAO();
$messages = $md->getHistory(echapJid($jid), date(DATE_ISO8601, strtotime($date)), $this->_pagination);
if(count($messages) > 0) {
Notification::append(false, $this->__('message.history', count($messages)));
}
foreach($messages as $message) {
if(!preg_match('#^\?OTR#', $message->body)) {
RPC::call('Chat.appendMessage', $this->prepareMessage($message), true);
}
}
}
/**
* @brief Configure a room
*
@ -368,7 +394,7 @@ class Chat extends WidgetBase
{
if(!$this->validateJid($room)) return;
$validate_subject = Validator::string()->length(0, 200);
$validate_subject = Validator::stringType()->length(0, 200);
if(!$validate_subject->validate($form->subject->value)) return;
$p = new SetSubject;
@ -451,7 +477,7 @@ class Chat extends WidgetBase
if(!$this->validateJid($jid)) return;
$md = new \Modl\MessageDAO();
$messages = $md->getContact(echapJid($jid), 0, 30);
$messages = $md->getContact(echapJid($jid), 0, $this->_pagination);
if(is_array($messages)) {
$messages = array_reverse($messages);
@ -501,7 +527,7 @@ class Chat extends WidgetBase
$message->color = stringToColor($message->session.$message->resource.$message->jidfrom.$message->type);
}
$message->published = prepareDate(strtotime($message->published));
$message->publishedPrepared = prepareDate(strtotime($message->published));
return $message;
}
@ -523,7 +549,7 @@ class Chat extends WidgetBase
*/
private function validateJid($jid)
{
$validate_jid = Validator::string()->noWhitespace()->length(6, 60);
$validate_jid = Validator::stringType()->noWhitespace()->length(6, 60);
if(!$validate_jid->validate($jid)) return false;
else return true;
}

View file

@ -7,7 +7,7 @@
<ul class="thin">
<li class="action">
<span class="icon gray emojis_open" onclick="Chat_ajaxSmiley()">
{$c->ajaxSmileyGet('😃')}
<img alt=":smiley:" class="emoji large" src="{$c->getSmileyPath('1f603')}">
</span>
<div class="action" data-jid="{$jid}" onclick="Chat.sendMessage(this.dataset.jid, {if="$muc"}true{else}false{/if})">
<i class="zmdi zmdi-mail-send"></i>

View file

@ -4,7 +4,9 @@
</div>
<ul class="flex middle active">
<li class="subheader block large">{$c->__('chat.frequent')}</li>
{if="$top"}
<li class="subheader block large">{$c->__('chat.frequent')}</li>
{/if}
{loop="$top"}
<li class="condensed block {if="$value->last > 60"} inactive{/if}"
onclick="Chats_ajaxOpen('{$value->jid}'); Chat_ajaxGet('{$value->jid}');">

View file

@ -2,76 +2,76 @@
<table class="emojis">
<tbody>
<tr class="active">
<td onclick="Chat.addSmiley(this);" data-emoji="😂"><img alt=":joy:" class="emoji" src="{$c->getSmileyPath('1f602')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😃"><img alt=":smiley:" class="emoji" src="{$c->getSmileyPath('1f603')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😄"><img alt=":smile:" class="emoji" src="{$c->getSmileyPath('1f604')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😆"><img alt=":laughing:" class="emoji" src="{$c->getSmileyPath('1f606')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😍"><img alt=":heart_eyes:" class="emoji" src="{$c->getSmileyPath('1f60d')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😉"><img alt=":wink:" class="emoji" src="{$c->getSmileyPath('1f609')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😂"><img alt=":joy:" class="emoji large" src="{$c->getSmileyPath('1f602')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😃"><img alt=":smiley:" class="emoji large" src="{$c->getSmileyPath('1f603')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😄"><img alt=":smile:" class="emoji large" src="{$c->getSmileyPath('1f604')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😆"><img alt=":laughing:" class="emoji large" src="{$c->getSmileyPath('1f606')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😍"><img alt=":heart_eyes:" class="emoji large" src="{$c->getSmileyPath('1f60d')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😉"><img alt=":wink:" class="emoji large" src="{$c->getSmileyPath('1f609')}"></td>
</tr>
<tr class="active">
<td onclick="Chat.addSmiley(this);" data-emoji="😠"><img alt=":angry:" class="emoji" src="{$c->getSmileyPath('1f620')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😜"><img alt=":stuck_out_tongue_winking_eye:" class="emoji" src="{$c->getSmileyPath('1f61c')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😝"><img alt=":stuck_out_tongue_closed_eyes:" class="emoji" src="{$c->getSmileyPath('1f61d')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😒"><img alt=":unamused:" class="emoji" src="{$c->getSmileyPath('1f612')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😓"><img alt=":sweat:" class="emoji" src="{$c->getSmileyPath('1f613')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😖"><img alt=":confounded:" class="emoji" src="{$c->getSmileyPath('1f616')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😠"><img alt=":angry:" class="emoji large" src="{$c->getSmileyPath('1f620')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😜"><img alt=":stuck_out_tongue_winking_eye:" class="emoji large" src="{$c->getSmileyPath('1f61c')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😝"><img alt=":stuck_out_tongue_closed_eyes:" class="emoji large" src="{$c->getSmileyPath('1f61d')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😒"><img alt=":unamused:" class="emoji large" src="{$c->getSmileyPath('1f612')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😓"><img alt=":sweat:" class="emoji large" src="{$c->getSmileyPath('1f613')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😖"><img alt=":confounded:" class="emoji large" src="{$c->getSmileyPath('1f616')}"></td>
</tr>
<tr class="active">
<td onclick="Chat.addSmiley(this);" data-emoji="😢"><img alt=":cry:" class="emoji" src="{$c->getSmileyPath('1f622')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😤"><img alt=":triumph:" class="emoji" src="{$c->getSmileyPath('1f624')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😥"><img alt=":disappointed_relieved:" class="emoji" src="{$c->getSmileyPath('1f625')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😪"><img alt=":sleepy:" class="emoji" src="{$c->getSmileyPath('1f62a')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😭"><img alt=":sob:" class="emoji" src="{$c->getSmileyPath('1f62d')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😱"><img alt=":scream:" class="emoji" src="{$c->getSmileyPath('1f631')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😢"><img alt=":cry:" class="emoji large" src="{$c->getSmileyPath('1f622')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😤"><img alt=":triumph:" class="emoji large" src="{$c->getSmileyPath('1f624')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😥"><img alt=":disappointed_relieved:" class="emoji large" src="{$c->getSmileyPath('1f625')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😪"><img alt=":sleepy:" class="emoji large" src="{$c->getSmileyPath('1f62a')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😭"><img alt=":sob:" class="emoji large" src="{$c->getSmileyPath('1f62d')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="😱"><img alt=":scream:" class="emoji large" src="{$c->getSmileyPath('1f631')}"></td>
</tr>
<tr class="active">
<td onclick="Chat.addSmiley(this);" data-emoji="🍌"><img alt=":banana:" class="emoji" src="{$c->getSmileyPath('1f34c')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍎"><img alt=":apple:" class="emoji" src="{$c->getSmileyPath('1f34e')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🌼"><img alt=":blossom:" class="emoji" src="{$c->getSmileyPath('1f33c')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🌵"><img alt=":cactus:" class="emoji" src="{$c->getSmileyPath('1f335')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🌹"><img alt=":rose:" class="emoji" src="{$c->getSmileyPath('1f339')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍄"><img alt=":mushroom:" class="emoji" src="{$c->getSmileyPath('1f344')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍌"><img alt=":banana:" class="emoji large" src="{$c->getSmileyPath('1f34c')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍎"><img alt=":apple:" class="emoji large" src="{$c->getSmileyPath('1f34e')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🌼"><img alt=":blossom:" class="emoji large" src="{$c->getSmileyPath('1f33c')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🌵"><img alt=":cactus:" class="emoji large" src="{$c->getSmileyPath('1f335')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🌹"><img alt=":rose:" class="emoji large" src="{$c->getSmileyPath('1f339')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍄"><img alt=":mushroom:" class="emoji large" src="{$c->getSmileyPath('1f344')}"></td>
</tr>
<tr class="active">
<td onclick="Chat.addSmiley(this);" data-emoji="🍔"><img alt=":hamburger:" class="emoji" src="{$c->getSmileyPath('1f354')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍕"><img alt=":pizza:" class="emoji" src="{$c->getSmileyPath('1f355')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍗"><img alt=":poultry_leg:" class="emoji" src="{$c->getSmileyPath('1f357')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍚"><img alt=":rice:" class="emoji" src="{$c->getSmileyPath('1f35a')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍜"><img alt=":ramen:" class="emoji" src="{$c->getSmileyPath('1f35c')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍣"><img alt=":sushi:" class="emoji" src="{$c->getSmileyPath('1f363')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍔"><img alt=":hamburger:" class="emoji large" src="{$c->getSmileyPath('1f354')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍕"><img alt=":pizza:" class="emoji large" src="{$c->getSmileyPath('1f355')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍗"><img alt=":poultry_leg:" class="emoji large" src="{$c->getSmileyPath('1f357')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍚"><img alt=":rice:" class="emoji large" src="{$c->getSmileyPath('1f35a')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍜"><img alt=":ramen:" class="emoji large" src="{$c->getSmileyPath('1f35c')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🍣"><img alt=":sushi:" class="emoji large" src="{$c->getSmileyPath('1f363')}"></td>
</tr>
<tr class="active">
<td onclick="Chat.addSmiley(this);" data-emoji="🛀"><img alt=":bath:" class="emoji" src="{$c->getSmileyPath('1f6c0')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🎧"><img alt=":headphones:" class="emoji" src="{$c->getSmileyPath('1f3a7')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🎮"><img alt=":video_game:" class="emoji" src="{$c->getSmileyPath('1f3ae')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🎫"><img alt=":ticket:" class="emoji" src="{$c->getSmileyPath('1f3ab')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="💼"><img alt=":briefcase:" class="emoji" src="{$c->getSmileyPath('1f4bc')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🎒"><img alt=":school_satchel:" class="emoji" src="{$c->getSmileyPath('1f392')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🛀"><img alt=":bath:" class="emoji large" src="{$c->getSmileyPath('1f6c0')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🎧"><img alt=":headphones:" class="emoji large" src="{$c->getSmileyPath('1f3a7')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🎮"><img alt=":video_game:" class="emoji large" src="{$c->getSmileyPath('1f3ae')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🎫"><img alt=":ticket:" class="emoji large" src="{$c->getSmileyPath('1f3ab')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="💼"><img alt=":briefcase:" class="emoji large" src="{$c->getSmileyPath('1f4bc')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🎒"><img alt=":school_satchel:" class="emoji large" src="{$c->getSmileyPath('1f392')}"></td>
</tr>
<tr class="active">
<td onclick="Chat.addSmiley(this);" data-emoji="💡"><img alt=":bulb:" class="emoji" src="{$c->getSmileyPath('1f4a1')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="📞"><img alt=":telephone_receiver:" class="emoji" src="{$c->getSmileyPath('1f4de')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🔥"><img alt=":fire:" class="emoji" src="{$c->getSmileyPath('1f525')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🕐"><img alt=":clock1:" class="emoji" src="{$c->getSmileyPath('1f550')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="✉"><img alt=":email:" class="emoji" src="{$c->getSmileyPath('2709')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="✏"><img alt=":pencil2:" class="emoji" src="{$c->getSmileyPath('270f')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="💡"><img alt=":bulb:" class="emoji large" src="{$c->getSmileyPath('1f4a1')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="📞"><img alt=":telephone_receiver:" class="emoji large" src="{$c->getSmileyPath('1f4de')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🔥"><img alt=":fire:" class="emoji large" src="{$c->getSmileyPath('1f525')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🕐"><img alt=":clock1:" class="emoji large" src="{$c->getSmileyPath('1f550')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="✉"><img alt=":email:" class="emoji large" src="{$c->getSmileyPath('2709')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="✏"><img alt=":pencil2:" class="emoji large" src="{$c->getSmileyPath('270f')}"></td>
</tr>
<tr class="active">
<td onclick="Chat.addSmiley(this);" data-emoji="💋"><img alt=":kiss:" class="emoji" src="{$c->getSmileyPath('1f48b')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="♥"><img alt=":hearts:" class="emoji" src="{$c->getSmileyPath('2665')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="💊"><img alt=":pill:" class="emoji" src="{$c->getSmileyPath('1f48a')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="💩"><img alt=":hankey:" class="emoji" src="{$c->getSmileyPath('1f4a9')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="☕"><img alt=":coffee:" class="emoji" src="{$c->getSmileyPath('2615')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="⏰"><img alt=":alarm_clock:" class="emoji" src="{$c->getSmileyPath('23f0')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="💋"><img alt=":kiss:" class="emoji large" src="{$c->getSmileyPath('1f48b')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="♥"><img alt=":hearts:" class="emoji large" src="{$c->getSmileyPath('2665')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="💊"><img alt=":pill:" class="emoji large" src="{$c->getSmileyPath('1f48a')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="💩"><img alt=":hankey:" class="emoji large" src="{$c->getSmileyPath('1f4a9')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="☕"><img alt=":coffee:" class="emoji large" src="{$c->getSmileyPath('2615')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="⏰"><img alt=":alarm_clock:" class="emoji large" src="{$c->getSmileyPath('23f0')}"></td>
</tr>
<tr class="active">
<td onclick="Chat.addSmiley(this);" data-emoji="🐷"><img alt=":pig:" class="emoji" src="{$c->getSmileyPath('1f437')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐵"><img alt=":monkey_face:" class="emoji" src="{$c->getSmileyPath('1f435')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐶"><img alt=":dog:" class="emoji" src="{$c->getSmileyPath('1f436')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐸"><img alt=":frog:" class="emoji" src="{$c->getSmileyPath('1f438')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐹"><img alt=":hamster:" class="emoji" src="{$c->getSmileyPath('1f439')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐻"><img alt=":bear:" class="emoji" src="{$c->getSmileyPath('1f43b')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐷"><img alt=":pig:" class="emoji large" src="{$c->getSmileyPath('1f437')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐵"><img alt=":monkey_face:" class="emoji large" src="{$c->getSmileyPath('1f435')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐶"><img alt=":dog:" class="emoji large" src="{$c->getSmileyPath('1f436')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐸"><img alt=":frog:" class="emoji large" src="{$c->getSmileyPath('1f438')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐹"><img alt=":hamster:" class="emoji large" src="{$c->getSmileyPath('1f439')}"></td>
<td onclick="Chat.addSmiley(this);" data-emoji="🐻"><img alt=":bear:" class="emoji large" src="{$c->getSmileyPath('1f43b')}"></td>
</tr>
</tbody>
</table>

View file

@ -49,11 +49,6 @@
margin-bottom: 1rem;
}
#chat_widget .emojis_open img {
width: 36px;
margin: 0.2rem;
}
/* Chatroom */
#chat_widget li span.icon {
@ -61,16 +56,16 @@
margin-top: 0.85rem;
}
#chat_widget li img:not(.emoji) {
#chat_widget li img:not(.emoji):not(.hfr) {
max-height: 30rem;
max-width: 100%;
display: block;
}
/*
#chat_widget li img.emoji {
padding: 0 0.25rem;
padding: 0.25rem;
}
*/
#chat_widget li.room {
min-height: 3rem;
margin-bottom: 0.5rem;

View file

@ -3,6 +3,8 @@ var Chat = {
right: null,
room: null,
previous: null,
date: null,
lastScroll: null,
addSmiley: function(element) {
var n = document.querySelector('#chat_textarea');
n.value = n.value + element.dataset.emoji;
@ -47,15 +49,28 @@ var Chat = {
Chat.right = div.firstChild.cloneNode(true);
div.innerHTML = room;
Chat.room = div.firstChild.cloneNode(true);
Chat.setScrollBehaviour();
},
setScrollBehaviour : function() {
var discussion = document.querySelector('#chat_widget div.contained');
discussion.onscroll = function() {
if(this.scrollTop < 1) {
var chat = document.querySelector('#chat_widget');
Chat.lastScroll = this.scrollHeight;
Chat_ajaxGetHistory(chat.dataset.jid, Chat.date);
}
};
},
appendMessages : function(messages) {
if(messages) {
Chat.date = messages[0].published;
for(var i = 0, len = messages.length; i < len; ++i ) {
Chat.appendMessage(messages[i]);
}
Chat.appendMessage(messages[i], false);
}
}
},
appendMessage : function(message) {
appendMessage : function(message, prepend) {
if(message.body == '') return;
var bubble = null;
@ -74,7 +89,7 @@ var Chat = {
}
bubble.querySelector('div').innerHTML = message.body;
bubble.querySelector('span.info').innerHTML = message.published;
bubble.querySelector('span.info').innerHTML = message.publishedPrepared;
bubble.querySelector('span.user').className = 'user ' + message.color;
bubble.querySelector('span.user').onclick = function(n) {
@ -117,21 +132,37 @@ var Chat = {
if(bubble) {
bubble.querySelector('div.bubble div').innerHTML = message.body;
bubble.querySelector('div.bubble span.info').innerHTML = message.published;
bubble.querySelector('div.bubble span.info').innerHTML = message.publishedPrepared;
if(prepend) {
Chat.date = message.published;
var discussion = document.querySelector('#chat_widget div.contained');
// We prepend
movim_prepend(id, bubble.outerHTML);
// And we scroll where we were
var scrollDiff = discussion.scrollHeight - Chat.lastScroll;
discussion.scrollTop += scrollDiff;
Chat.lastScroll = discussion.scrollHeight;
} else {
movim_append(id, bubble.outerHTML);
}
movim_append(id, bubble.outerHTML);
bubble.querySelector('div.bubble').className = 'bubble';
if(bubble.className.indexOf('oppose') > -1) MovimTpl.scrollPanel();
if(bubble.className.indexOf('oppose') > -1
&& prepend == null) MovimTpl.scrollPanel();
}
}
if(scrolled) MovimTpl.scrollPanel();
if(scrolled && prepend == null) MovimTpl.scrollPanel();
}
}
MovimWebsocket.attach(function() {
var jid = document.querySelector('#chat_widget').dataset.jid;
var chat = document.querySelector('#chat_widget');
var jid = chat.dataset.jid;
if(jid) {
MovimTpl.showPanel();
Chat_ajaxGet(jid);

View file

@ -4,6 +4,7 @@ encrypted = Encrypted message
composing = Composing...
paused = Paused...
gone = Contact gone
history = %s messages retrieved
[chat]
attention = %s needs your attention

View file

@ -32,13 +32,6 @@ class Chats extends WidgetBase
}
$this->ajaxOpen($from, false);
/*
$chats = Cache::c('chats');
if(!array_key_exists($from, $chats)) {
$this->ajaxOpen($from);
} else {
RPC::call('Chats.prepend', $from, $this->prepareChat($from));
}*/
}
}
@ -217,7 +210,7 @@ class Chats extends WidgetBase
private function validateJid($jid)
{
$validate_jid = Validator::string()->noWhitespace()->length(6, 40);
$validate_jid = Validator::stringType()->noWhitespace()->length(6, 40);
if($validate_jid->validate($jid)) return true;
else return false;

View file

@ -16,6 +16,7 @@ var Chats = {
Chats.reset(items);
Notification_ajaxClear('chat|' + this.dataset.jid);
Notification.current('chat|' + this.dataset.jid);
document.querySelector('#chat_widget').dataset.jid = this.dataset.jid;
movim_add_class(this, 'active');
}
@ -24,6 +25,7 @@ var Chats = {
Notification_ajaxClear('chat|' + this.dataset.jid);
Notification.current('chat');
Chats_ajaxClose(this.dataset.jid);
delete document.querySelector('#chat_widget').dataset.jid;
MovimTpl.hidePanel();
}
}

View file

@ -2,7 +2,7 @@
<div class="placeholder icon">
<h1>{$c->__('chats.empty_title')}</h1>
<h4>{$c->___('chats.empty', '<i class="zmdi zmdi-plus"></i>', '<a href="'.$c->route('contact').'"><i class="zmdi zmdi-accounts"></i>', '</a>')}</h4>
<h4>{$c->___('chats.empty', '<i class="zmdi zmdi-plus"></i>', '<a href="'.$c->route('contact').'"><i class="zmdi zmdi-accounts"></i> ', '</a>')}</h4>
</div>
<a class="button action color" onclick="MovimTpl.toggleActionButton()">
<i class="zmdi zmdi-plus"></i>

View file

@ -1,6 +1,6 @@
[chats]
empty_title = No chats yet...
empty = Open a new conversation by clicking on the %s button bellow or visit the %s Contacts%s page.
empty = Open a new conversation by clicking on the %s button bellow or visit the %sContacts%s page.
add = Chat with a contact
frequent = Frequent contacts
more = Load more contacts

View file

@ -19,6 +19,7 @@
*/
use Moxl\Xec\Action\Storage\Set;
use Respect\Validation\Validator;
class Config extends WidgetBase
{
@ -59,15 +60,19 @@ class Config extends WidgetBase
$data = (array)$package->content;
$this->user->setConfig($data);
$html = $this->prepareConfigForm();
$this->refreshConfig();
RPC::call('movim_fill', 'config_widget', $html);
RPC::call('Config.load');
Notification::append(null, $this->__('config.updated'));
}
function ajaxSubmit($data)
{
if(!$this->validateForm($data)) {
$this->refreshConfig();
Notification::append(null, $this->__('config.not_valid'));
return;
}
$config = $this->user->getConfig();
if(isset($config))
$data = array_merge($config, $data);
@ -78,6 +83,25 @@ class Config extends WidgetBase
->request();
}
private function refreshConfig()
{
$html = $this->prepareConfigForm();
RPC::call('movim_fill', 'config_widget', $html);
RPC::call('Config.load');
}
private function validateForm($data)
{
$l = Movim\i18n\Locale::start();
if(Validator::in(array_keys($l->getList()))->validate($data['language'])
&& Validator::in(array('show', 'hide'))->validate($data['roster'])
&& ($data['cssurl'] == '' || Validator::url()->validate($data['cssurl'])))
return true;
return false;
}
function display()
{
$this->view->assign('form', $this->prepareConfigForm());

View file

@ -7,13 +7,13 @@
<option value="en">English (default)</option>
{loop="$languages"}
{if="$key == $conf.language"}
<option
value="{$key}"
<option
value="{$key}"
selected="selected">
{$value}
</option>
{else}
<option
<option
value="{$key}">
{$value}
</option>
@ -38,115 +38,19 @@
<label for="roster">{$c->__('config.roster')}</label>
</div>
<div class="clear"></div>
<br />
<!--
<h3>{$c->__('config.notifications')}</h3>
<h3>{$c->__('config.advanced')}</h3>
<div class="block">
<div class="checkbox">
<input
type="checkbox"
id="privacy"
name="privacy"
{if="$me->privacy"}
checked
{/if}
onchange="{$privacy}">
<label for="privacy"></label>
</div>
<label for="language">{$c->__('notifications.message')}</label>
<input name="cssurl" class="content" placeholder="http://myserver.com/style.css" value="{$conf.cssurl}" type="url">
<label for="cssurl">{$c->__('cssurl.label')}</label>
</div>
<div class="block">
<div class="checkbox">
<input
type="checkbox"
id="privacy"
name="privacy"
{if="$me->privacy"}
checked
{/if}
onchange="{$privacy}">
<label for="privacy"></label>
</div>
<label for="language">{$c->__('notifications.desktop')}</label>
</div>-->
<!--
<h3>{$c->__('config.appearence')}</h3>-->
<!--<div class="block large" id="nav_color">
<a
type="button"
style="width: 45%; float: right;"
class="button flat">
{$c->__('button.reset')}
</a>
<input
style="box-shadow: none; width: 50%; float: left;"
name="color"
class="color"
value="
{if="isset($color)"}
{$color}
{else}
082D50
{/if}
">
<label for="color"><i class="fa fa-adjust"></i> {$c->__('config.background_color')}</label>
</div>-->
<!--
<div class="block large" id="font_size">
<label for="size"><i class="fa fa-font"></i> {$c->__('config.font_size')}</label>
<a
type="button"
class="button flat">
{$c->__('button.reset')}
</a>
<span>
12
<input
id="slide"
type="range"
min="12"
max="16"
step="0.5"
value="
{if="isset($size)"}
{$size}
{else}
14
{/if}
"
name="size"
style="width: 45%;"
/>
16
</span>
<span id="currentsize">
{if="isset($size)"}
{$size}
{else}
14
{/if}
px
</span>
</div>
-->
<!--<label id="lock" for="soundnotif">{$c->t('Enable Sound Notification:'); ?></label>
<input type="checkbox" name="soundnotif" value="soundnotif" checked="checked" /><br /> -->
<!--<input value="{$c->t('Submit'); ?>" onclick="<?php echo $submit; ?>" type="button" class="button icon yes merged right" style="float: right;">
<input type="reset" value="{$c->t('Reset'); ?>" class="button icon no merged left" style="float: right;">-->
<div class="clear padded"></div>
<a
onclick="{$submit}"
<a
onclick="{$submit}"
class="button color oppose" >
{$c->__('button.save')}
</a>
<div class="clear"></div>
</form>
<!--
<div class="message info">{$c->__('config.info')}</div>-->

View file

@ -5,9 +5,13 @@ roster = Roster display
roster_show = Show the offline contacts
roster_hide = Hide the offline contacts
appearence = Appearence
info = This configuration is shared wherever you are connected
updated = Configuration updated
not_valid = Configuration invalid
advanced = Advanced Configuration
[notifications]
message = Notify on incoming message
desktop = Use desktop notifications
[cssurl]
label = Custom CSS URL for your blog

View file

@ -178,7 +178,7 @@ class Contact extends WidgetBase
function ajaxPublic($page = 0)
{
$validate_page = Validator::int();
$validate_page = Validator::intType();
if(!$validate_page->validate($page)) return;
RPC::call('MovimTpl.fill', '#public_list', $this->preparePublic($page));
@ -221,7 +221,7 @@ class Contact extends WidgetBase
$view = $this->tpl();
$pd = new \Modl\PostnDAO;
$gallery = $pd->getGallery($jid);
$gallery = $pd->getGallery($jid, 0, 12);
$blog = $pd->getPublic($jid, 'urn:xmpp:microblog:0', 0, 4);
$presencestxt = getPresencesTxt();
@ -289,7 +289,7 @@ class Contact extends WidgetBase
*/
private function validateJid($jid)
{
$validate_jid = Validator::string()->noWhitespace()->length(6, 60);
$validate_jid = Validator::stringType()->noWhitespace()->length(6, 60);
if(!$validate_jid->validate($jid)) return false;
else return true;
}

View file

@ -176,7 +176,7 @@
<span class="info">{$value->published|strtotime|prepareDate}</span>
</li>
{/loop}
<a href="{$c->route('blog', array($jid))}" target="_blank" class="block large">
<a href="{$c->route('blog', array($contact->jid))}" target="_blank" class="block large">
<li class="action">
<div class="action">
<i class="zmdi zmdi-chevron-right"></i>
@ -315,7 +315,7 @@
<li style="background-image: url('{$attachements['pictures'][0]['href']}');"
onclick="movim_reload('{$c->route('news', $value->nodeid)}')">
<nav>
{$attachements['pictures'][0]['title']}
<span>{$value->title}</span>
</nav>
</li>
{/loop}

View file

@ -381,6 +381,11 @@ class Group extends WidgetBase
return $html;
}
public function preparePost($p) {
$pw = new Post;
return $pw->preparePost($p, true);
}
private function prepareHeader($server, $node)
{
$pd = new \Modl\ItemDAO;
@ -416,8 +421,8 @@ class Group extends WidgetBase
private function validateServerNode($server, $node)
{
$validate_server = Validator::string()->noWhitespace()->length(6, 40);
$validate_node = Validator::string()->length(3, 100);
$validate_server = Validator::stringType()->noWhitespace()->length(6, 40);
$validate_node = Validator::stringType()->length(3, 100);
if(!$validate_server->validate($server)
|| !$validate_node->validate($node)

View file

@ -1,4 +1,6 @@
{loop="$posts"}
{$c->preparePost($value)}
<!--
{$attachements = $value->getAttachements()}
<article id="{$value->nodeid}" class="block">
{if="isset($attachements.pictures)"}
@ -36,6 +38,9 @@
-
{/if}
{$value->published|strtotime|prepareDate}
{if="$value->published != $value->updated"}
- <i class="zmdi zmdi-edit"></i> {$value->updated|strtotime|prepareDate}
{/if}
</p>
</li>
</ul>
@ -53,6 +58,19 @@
</content>
</section>
<footer>
{$tags = $value->getTags()}
{if="isset($tags)"}
<ul class="middle">
<li>
<span class="icon zmdi zmdi-tag gray"></span>
<span>
{loop="$tags"}
<a target="_blank" href="{$c->route('tag', array($value))}">#{$value}</a>
{/loop}
</span>
</li>
</ul>
{/if}
<ul class="thin">
{if="isset($attachements.links)"}
{loop="$attachements.links"}
@ -171,7 +189,7 @@
</ul>
{/if}
<br />
</article>
</article>-->
{/loop}
{if="$posts != null && count($posts) >= $paging-1"}
<ul class="active thick">

View file

@ -118,7 +118,7 @@ class Groups extends WidgetBase
{
if(!$this->validateServer($server)) return;
$validate_name = Validator::string()->length(4, 80);
$validate_name = Validator::stringType()->length(4, 80);
if(!$validate_name->validate($form->name->value)) {
Notification::append(null, $this->__('groups.name_error'));
return;
@ -191,7 +191,7 @@ class Groups extends WidgetBase
*/
private function validateServer($server)
{
$validate_server = Validator::string()->noWhitespace()->length(6, 40);
$validate_server = Validator::stringType()->noWhitespace()->length(6, 40);
if(!$validate_server->validate($server)) return false;
else return true;
}

View file

@ -1,6 +1,6 @@
{if="$subscriptions == null"}
<ul class="thick">
<div class="placeholder icon pages">
<div class="placeholder icon bookmark">
<h1>{$c->__('groups.empty_title')}</h1>
<h4>{$c->__('groups.empty_text1')}</h4>
<h4>{$c->__('groups.empty_text2')}</h4>

View file

@ -4,7 +4,7 @@
{$a = '1f600'}
<li>
<h2>{$c->__('hello.enter_title')}</h2>
<p>{$c->__('hello.enter_paragraph')} <img alt=":smiley:" class="emoji" src="{$a|getSmileyPath:false}"></p>
<p class="all">{$c->__('hello.enter_paragraph')} <img alt=":smiley:" class="emoji" src="{$a|getSmileyPath}"></p>
</li>
</ul>
<ul class="middle">
@ -14,7 +14,7 @@
<i class="zmdi zmdi-cloud-outline on_desktop"></i>
</span>
<span>{$c->__('hello.menu_title')}</span>
<p>{$c->__('hello.menu_paragraph')}</p>
<p class="all">{$c->__('hello.menu_paragraph')}</p>
</li>
</ul>
{/if}
@ -77,6 +77,7 @@
</li>
{/if}
{loop="$news"}
{$attachements = $value->getAttachements()}
<li class="block condensed"
data-id="{$value->nodeid}"
{if="$value->title != null"}

View file

@ -4,7 +4,23 @@ class Help extends WidgetBase
{
function load()
{
$this->addjs('help.js');
}
function ajaxAddChatroom()
{
$r = new Rooms;
$r->ajaxChatroomAdd(
array(
'jid' => 'movim@conference.movim.eu',
'name'=> 'Movim Chatroom',
'nick' => false,
'autojoin' => 0
)
);
$r->ajaxJoin('movim@conference.movim.eu');
RPC::call('movim_redirect', $this->route('chat'));
}
function display()

View file

@ -1,9 +1,9 @@
<div class="tabelem" title="{$c->__('page.help')}" id="help_widget">
<ul class="thick active">
<li class="condensed action">
<a href="http://wiki.movim.eu" target="_blank">
<a href="https://github.com/edhelas/movim/wiki" target="_blank">
<span class="icon bubble color blue">
<i class="zmdi zmdi-format-subject"></i>
<i class="zmdi zmdi-github-alt"></i>
</span>
<span>{$c->__('wiki.question')}</span>
<p>{$c->__('wiki.button')}</p>
@ -13,7 +13,7 @@
</div>
</li>
<li class="condensed action">
<a href="http://wiki.movim.eu/en:mailing_list" target="_blank">
<a href="https://github.com/edhelas/movim/wiki/Mailing-List" target="_blank">
<span class="icon bubble color orange">
<i class="zmdi zmdi-email"></i>
</span>
@ -24,12 +24,15 @@
<i class="zmdi zmdi-chevron-right"></i>
</div>
</li>
<li class="condensed">
<span class="icon bubble color green">
<i class="zmdi zmdi-comment-text-alt"></i>
</span>
<span>{$c->__('chatroom.question')}</span>
<p>{$c->__('chatroom.button')}<br/>movim@conference.movim.eu</p>
<li class="condensed action" onclick="Help_ajaxAddChatroom()">
<span class="icon bubble color green">
<i class="zmdi zmdi-comment-text-alt"></i>
</span>
<span>{$c->__('chatroom.question')}</span>
<p>{$c->__('chatroom.button')}<br/>movim@conference.movim.eu</p>
<div class="action">
<i class="zmdi zmdi-accounts-add"></i>
</div>
</li>
</ul>
<!--

View file

@ -20,4 +20,4 @@ button = Join the Mailing List
[chatroom]
question = Chat with the team ?
button = Join the Chatroom
button = Add the chatroom

View file

@ -167,7 +167,7 @@ class Login extends WidgetBase
// First we check the form
$validate_login = Validator::email()->length(6, 40);
$validate_password = Validator::string()->length(4, 40);
$validate_password = Validator::stringType()->length(4, 40);
if(!$validate_login->validate($login)) {
$this->showErrorBlock('login_format');

View file

@ -24,10 +24,10 @@
</ul>
</section>
<div>
<a class="button flat" href="{$c->route('about')}">
<a class="button flat" href="{$c->route('about')}" title="{$c->__('page.about')}">
<i class="zmdi zmdi-help"></i>
</a>
<a class="button flat" href="{$c->route('admin')}">
<a class="button flat" href="{$c->route('admin')}" title="{$c->__('page.administration')}">
<i class="zmdi zmdi-pages"></i>
</a>
<span class="button flat" onclick="Login.toForm()">{$c->__('form.another_account')}</span>

View file

@ -21,7 +21,7 @@
name="login">
<div>
<input type="email" name="login" id="login" autofocus required disabled
placeholder="{$c->__('form.username')}"/>
placeholder="username@server.com"/>
<label for="login">{$c->__('form.username')}</label>
</div>
<div>
@ -38,7 +38,7 @@
disabled
data-loading="{$c->__('button.connecting')}"
value="{$c->__('button.come_in')}"
class="button flat"/>
class="button flat"/>
</div>
<a id="return_sessions" class="button flat" href="#" onclick="Login.toChoose()">
{$c->__('account.title')}

View file

@ -27,7 +27,7 @@ class LoginAnonymous extends WidgetBase
function ajaxLogin($username)
{
$validate_user = Validator::string()->length(4, 40);
$validate_user = Validator::stringType()->length(4, 40);
if(!$validate_user->validate($username)) {
Notification::append(null, $this->__('login_anonymous.bad_username'));
return;

View file

@ -5,6 +5,7 @@
{/if}
{loop="$items"}
{$attachements = $value->getAttachements()}
<li
tabindex="{$page*$paging+$key+1}"
class="block large condensed "
@ -55,6 +56,7 @@
</a>
{/if}
{$value->published|strtotime|prepareDate}
{if="$value->published != $value->updated"}<i class="zmdi zmdi-edit"></i>{/if}
</p>
{if="$value->privacy"}

View file

@ -7,6 +7,7 @@ var Notification = {
tab_counter2 : 0,
tab_counter1_key : 'chat',
tab_counter2_key : 'news',
document_title_init : null,
document_title : document.title,
notifs_key : '',
favicon : null,
@ -141,6 +142,8 @@ var Notification = {
}
}
Notification.document_title_init = document.title;
MovimWebsocket.attach(function() {
if(typeof Favico != 'undefined') {
Notification.favicon = new Favico({
@ -155,7 +158,8 @@ MovimWebsocket.attach(function() {
Notification.electron = remote.getCurrentWindow();
}
Notification.document_title = document.title;
Notification.document_title = Notification.document_title_init;
Notification.tab_counter1 = Notification.tab_counter2 = 0;
Notification_ajaxGet();
Notification.current(Notification.notifs_key);
});

View file

@ -20,6 +20,7 @@
use Moxl\Xec\Action\Pubsub\PostPublish;
use Moxl\Xec\Action\Pubsub\PostDelete;
use Moxl\Xec\Action\Pubsub\GetItem;
use Moxl\Xec\Action\Microblog\CommentsGet;
use Moxl\Xec\Action\Microblog\CommentCreateNode;
use Moxl\Xec\Action\Microblog\CommentPublish;
@ -96,7 +97,16 @@ class Post extends WidgetBase
function ajaxGetPost($id)
{
$html = $this->preparePost($id);
$pd = new \Modl\PostnDAO;
$p = $pd->getItem($id);
$gi = new GetItem;
$gi->setTo($p->origin)
->setNode($p->node)
->setId($p->nodeid)
->request();
$html = $this->preparePost($p);
$header = $this->prepareHeader($id);
Header::fill($header);
@ -137,8 +147,8 @@ class Post extends WidgetBase
{
$comment = trim($form->comment->value);
$validate_comment = Validator::string()->notEmpty();
$validate_id = Validator::string()->length(6, 128)->noWhitespace();
$validate_comment = Validator::stringType()->notEmpty();
$validate_id = Validator::stringType()->length(6, 128)->noWhitespace();
if(!$validate_comment->validate($comment)
|| !$validate_id->validate($id)) return;
@ -178,19 +188,18 @@ class Post extends WidgetBase
return $view->draw('_post_header', true);
}
function preparePost($id)
function preparePost($p, $external = false, $public = false)
{
$pd = new \Modl\PostnDAO;
$p = $pd->getItem($id);
$view = $this->tpl();
if(isset($p)) {
if(isset($p->commentplace)) {
if(isset($p->commentplace) && !$external) {
$this->ajaxGetComments($p->commentplace, $p->nodeid);
}
$view->assign('recycled', false);
$view->assign('external', $external);
$view->assign('public', $public);
// Is it a recycled post ?
if($p->getContact()->jid
@ -203,13 +212,13 @@ class Post extends WidgetBase
$view->assign('post', $p);
$view->assign('attachements', $p->getAttachements());
return $view->draw('_post', true);
} else {
} elseif(!$external) {
return $this->prepareEmpty();
}
}
function ajaxTogglePrivacy($id) {
$validate = Validator::string()->length(6, 128);
$validate = Validator::stringType()->length(6, 128);
if(!$validate->validate($id))
return;
@ -232,9 +241,15 @@ class Post extends WidgetBase
}
}
function getComments($post)
{
$pd = new \Modl\PostnDAO();
return $pd->getComments($post);
}
function display()
{
$validate_nodeid = Validator::string()->length(10, 100);
$validate_nodeid = Validator::stringType()->length(10, 100);
$this->view->assign('nodeid', false);
if($validate_nodeid->validate($this->get('n'))) {

View file

@ -1,9 +1,11 @@
<article class="block">
{if="isset($attachements.pictures)"}
<header
class="big"
style="
background-image: linear-gradient(to bottom, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.5) 100%), url('{$attachements['pictures'][0]['href']}');">
{if="($public && $post->isPublic()) || !$public"}
<header
class="big"
style="
background-image: linear-gradient(to bottom, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.5) 100%), url('{$attachements['pictures'][0]['href']}');">
{/if}
{else}
<header>
{/if}
@ -34,145 +36,233 @@
</a>
{/if}
<h2 {if="$post->title != null"}title="{$post->title|strip_tags}"{/if}>
{if="$post->title != null"}
{$post->title}
{else}
{$c->__('post.default_title')}
{/if}
<a {if="$public"}
{if="$post->isMicroblog()"}
href="{$c->route('blog', array($post->origin, $post->nodeid))}"
{else}
href="{$c->route('node', array($post->origin, $post->node, $post->nodeid))}"
{/if}
{else}
href="{$c->route('news', $post->nodeid)}"
{/if}
>
{if="$post->title != null"}
{$post->title}
{else}
{$c->__('post.default_title')}
{/if}
</a>
</h2>
<p>
{if="$contact->getTrueName() != ''"}
{if="!$public"}
<a href="{$c->route('contact', $contact->jid)}">
{/if}
<i class="zmdi zmdi-account"></i> {$contact->getTrueName()}
</a>
{if="!$public"}</a>{/if}
{/if}
{if="$post->node != 'urn:xmpp:microblog:0'"}
{$post->origin} /
{if="!$public"}
<a href="{$c->route('group', array($post->origin, $post->node))}">
{/if}
<i class="zmdi zmdi-pages"></i> {$post->node}
</a>
{if="!$public"}</a>{/if}
{/if}
{$post->published|strtotime|prepareDate}
{if="$post->published != $post->updated"}
- <i class="zmdi zmdi-edit"></i> {$post->updated|strtotime|prepareDate}
{/if}
</p>
</li>
</ul>
</header>
{if="$public && !$post->isPublic()"}
<ul class="thick">
<li>
<span class="icon color gray bubble">
<i class="zmdi zmdi-lock"></i>
</span>
<p class="center"> {$c->__('blog.private')} - <a href="{$c->route('main')}">{$c->__('page.login')}</a></p>
</li>
</ul>
<br />
{else}
<section>
<content>
{if="$post->isShort() && isset($attachements.pictures)"}
{loop="$attachements.pictures"}
<a href="{$value.href}" class="alternate" target="_blank">
<img class="big_picture" type="{$value.type}" src="{$value.href|urldecode}"/>
</a>
{/loop}
{elseif="$post->getYoutube()"}
<div class="video_embed">
<iframe src="https://www.youtube.com/embed/{$post->getYoutube()}" frameborder="0" allowfullscreen></iframe>
</div>
{/if}
{$post->contentcleaned}
</content>
</section>
<section>
<content>
{if="$post->isShort() && isset($attachements.pictures)"}
{loop="$attachements.pictures"}
<a href="{$value.href}" class="alternate" target="_blank">
<img class="big_picture" type="{$value.type}" src="{$value.href|urldecode}"/>
</a>
{/loop}
<footer>
{$tags = $post->getTags()}
{if="isset($tags)"}
<ul class="middle">
<li>
<span class="icon zmdi zmdi-tag gray"></span>
<span>
{loop="$tags"}
<a target="_blank" href="{$c->route('tag', array($value))}">#{$value}</a>
{/loop}
</span>
</li>
</ul>
{/if}
{$post->contentcleaned}
</content>
</section>
<footer>
<ul class="middle divided spaced">
{if="isset($attachements.links)"}
{loop="$attachements.links"}
{if="substr($value.href, 0, 5) != 'xmpp:' && filter_var($value.href, FILTER_VALIDATE_URL)"}
<ul class="middle divided spaced">
{if="isset($attachements.links)"}
{loop="$attachements.links"}
{if="substr($value.href, 0, 5) != 'xmpp:' && filter_var($value.href, FILTER_VALIDATE_URL)"}
<li>
<span class="icon">
<img src="https://icons.duckduckgo.com/ip2/{$value.url.host}.ico"/>
</span>
<a href="{$value.href}" class="alternate" target="_blank">
<span>{$value.href|urldecode}</span>
</a>
</li>
{/if}
{/loop}
{/if}
{if="isset($attachements.files)"}
{loop="$attachements.files"}
<li>
<span class="icon">
<img src="https://icons.duckduckgo.com/ip2/{$value.url.host}.ico"/>
</span>
<a href="{$value.href}" class="alternate" target="_blank">
<a
href="{$value.href}"
class="enclosure"
type="{$value.type}"
target="_blank">
<span class="icon gray">
<span class="zmdi zmdi-attachment-alt"></span>
</span>
<span>{$value.href|urldecode}</span>
</a>
</li>
{/if}
{/loop}
{/if}
{if="isset($attachements.files)"}
{loop="$attachements.files"}
<li>
<a
href="{$value.href}"
class="enclosure"
type="{$value.type}"
target="_blank">
<span class="icon gray">
<span class="zmdi zmdi-attachment-alt"></span>
</span>
<span>{$value.href|urldecode}</span>
{/loop}
{/if}
</ul>
{if="!$post->isShort() && isset($attachements.pictures)"}
<ul class="flex middle">
{loop="$attachements.pictures"}
<li class="block pic">
<span class="icon gray">
<i class="zmdi zmdi-image"></i>
</span>
<a href="{$value.href}" class="alternate" target="_blank">
<img type="{$value.type}" src="{$value.href|urldecode}"/>
</a>
</li>
{/loop}
</ul>
{/if}
</ul>
{if="!$post->isShort() && isset($attachements.pictures)"}
<ul class="flex middle">
{loop="$attachements.pictures"}
<li class="block pic">
<span class="icon gray">
<i class="zmdi zmdi-image"></i>
</span>
<a href="{$value.href}" class="alternate" target="_blank">
<img type="{$value.type}" src="{$value.href|urldecode}"/>
</a>
</li>
{/loop}
</ul>
{/if}
{if="$post->isMine()"}
<ul class="middle">
<li class="action">
<form>
<div class="action">
<div class="checkbox">
<input
type="checkbox"
id="privacy"
name="privacy"
{if="$post->privacy"}
checked
{/if}
onclick="Post_ajaxTogglePrivacy('{$post->nodeid}')">
<label for="privacy"></label>
{if="$post->isMine() && !$public"}
<ul class="middle">
<li class="action">
<form>
<div class="action">
<div class="checkbox">
<input
type="checkbox"
id="privacy"
name="privacy"
{if="$post->privacy"}
checked
{/if}
{if="$external"}
onclick="Group_ajaxTogglePrivacy('{$post->nodeid}')"
{else}
onclick="Post_ajaxTogglePrivacy('{$post->nodeid}')"
{/if}
>
<label for="privacy"></label>
</div>
</div>
</form>
<span class="icon gray">
<i class="zmdi zmdi-portable-wifi"></i>
</span>
<span>
<a target="_blank" href="{$post->getPublicUrl()}">
{$c->__('post.public')}
</a>
</span>
</li>
</ul>
{/if}
</footer>
{if="$recycled"}
<a href="{$c->route('contact', $post->getContact()->jid)}">
<ul class="active middle">
<li class="condensed action">
<div class="action">
<i class="zmdi zmdi-chevron-right"></i>
</div>
</form>
<span class="icon gray">
<i class="zmdi zmdi-portable-wifi"></i>
</span>
<span>
<a target="_blank" href="{$post->getPublicUrl()}">
{$c->__('post.public')}
</a>
</span>
</li>
</ul>
{$url = $post->getContact()->getPhoto('s')}
{if="$url"}
<span class="icon bubble" style="background-image: url('{$url}');">
<i class="zmdi zmdi-loop"></i>
</span>
{else}
<span class="icon bubble color {$post->getContact()->jid|stringToColor}">
<i class="zmdi zmdi-loop"></i>
</span>
{/if}
<span>{$c->__('post.repost', $post->getContact()->getTrueName())}</span>
<p>{$c->__('post.repost_profile', $post->getContact()->getTrueName())}</p>
</li>
</ul>
</a>
{/if}
</footer>
{if="$recycled"}
<a href="{$c->route('contact', $post->getContact()->jid)}">
<ul class="active middle">
<li class="condensed action">
<div class="action">
<i class="zmdi zmdi-chevron-right"></i>
</div>
{$url = $post->getContact()->getPhoto('s')}
{if="$url"}
<span class="icon bubble" style="background-image: url('{$url}');">
<i class="zmdi zmdi-loop"></i>
</span>
{else}
<span class="icon bubble color {$post->getContact()->jid|stringToColor}">
<i class="zmdi zmdi-loop"></i>
</span>
{/if}
<span>{$c->__('post.repost', $post->getContact()->getTrueName())}</span>
<p>{$c->__('post.repost_profile', $post->getContact()->getTrueName())}</p>
</li>
</ul>
</a>
{if="$external"}
{$comments = $c->getComments($post)}
{if="$comments"}
<ul class="spaced middle">
<li class="subheader">
{$c->__('post.comments')}
<span class="info">{$comments|count}</span>
</li>
{loop="$comments"}
<li class="condensed">
{$url = $value->getContact()->getPhoto('s')}
{if="$url"}
<span class="icon bubble">
<img src="{$url}">
</span>
{else}
<span class="icon bubble color {$value->getContact()->jid|stringToColor}">
<i class="zmdi zmdi-account"></i>
</span>
{/if}
<span class="info">{$value->published|strtotime|prepareDate}</span>
<span>
{$value->getContact()->getTrueName()}
</span>
<p class="all">
{if="$value->title"}
{$value->title}
{else}
{$value->contentraw}
{/if}
</p>
</li>
{/loop}
</ul><br />
{/if}
{else}
<div id="comments"></div>
{/if}
{/if}
<div id="comments"></div>
</article>

View file

@ -29,7 +29,11 @@
</a>
</span>
<p class="all">
{$value->contentraw}
{if="$value->contentraw"}
{$value->contentraw}
{else}
{$value->title}
{/if}
</p>
</li>
{/loop}

View file

@ -3,6 +3,7 @@
<ul class="flex card shadow active">
{loop="$posts"}
{if="!filter_var($value->origin, FILTER_VALIDATE_EMAIL)"}
{$attachements = $value->getAttachements()}
<li
class="block condensed"
data-id="{$value->nodeid}"
@ -41,7 +42,7 @@
{/if}
</p>
</li>
{/if}
{/if}
{/loop}
</ul>
<ul class="active thick">

View file

@ -67,20 +67,20 @@ class Publish extends WidgetBase
{
if(!$this->validateServerNode($server, $node)) return;
$item = false;
$post = false;
if($id) {
$pd = new \modl\PostnDAO();
$p = $pd->getItem($id);
if($p->isEditable()) {
$item = $p;
$post = $p;
}
}
$view = $this->tpl();
$view->assign('to', $server);
$view->assign('node', $node);
$view->assign('item', $item);
$view->assign('item', $post);
RPC::call('MovimTpl.fill', 'main section > div:nth-child(2)', $view->draw('_publish_create', true));
@ -90,6 +90,7 @@ class Publish extends WidgetBase
$view = $this->tpl();
$view->assign('server', $server);
$view->assign('node', $node);
$view->assign('post', $post);
$view->assign('item', $item);
Header::fill($view->draw('_publish_header', true));
@ -160,7 +161,7 @@ class Publish extends WidgetBase
$p = new PostPublish;
$p->setFrom($this->user->getLogin())
->setTo($form->to->value)
->setTitle($form->title->value)
->setTitle(htmlspecialchars($form->title->value))
->setNode($form->node->value);
//->setLocation($geo)
//->enableComments()
@ -179,6 +180,26 @@ class Publish extends WidgetBase
if($form->id->value != '') {
$p->setId($form->id->value);
$pd = new \modl\PostnDAO();
$post = $pd->getItem($form->id->value);
if(isset($post)) {
$p->setPublished(strtotime($post->published));
}
}
if(Validator::stringType()->notEmpty()->alnum(',')->validate($form->tags->value)) {
$p->setTags(array_unique(
array_filter(
array_map(
function($value) {
return trim(strtolower($value));
},
explode(',', $form->tags->value)
)
)
));
}
if($form->embed->value != '' && filter_var($form->embed->value, FILTER_VALIDATE_URL)) {
@ -186,10 +207,12 @@ class Publish extends WidgetBase
$embed = Embed\Embed::create($form->embed->value);
$p->setLink($form->embed->value);
if($embed->type == 'photo') {
if(in_array($embed->type, array('photo', 'rich'))) {
$key = key($embed->images);
$p->setImage($embed->images[0]['value'], $embed->title, $embed->images[0]['mime']);
} else {
}
if($embed->type !== 'photo') {
$content_xhtml .= $this->prepareEmbed($embed);
}
} catch(Exception $e) {
@ -198,11 +221,11 @@ class Publish extends WidgetBase
}
if($content != '') {
$p->setContent($content);
$p->setContent(htmlspecialchars($content));
}
if($content_xhtml != '') {
$p->setContentXhtml(rawurldecode($content_xhtml));
$p->setContentXhtml($content_xhtml);
}
$p->request();
@ -225,12 +248,15 @@ class Publish extends WidgetBase
$embed = Embed\Embed::create($url);
$html = $this->prepareEmbed($embed);
if($embed->type == 'photo') {
RPC::call('movim_fill', 'preview', '');
RPC::call('movim_fill', 'gallery', '');
if(in_array($embed->type, array('photo', 'rich'))) {
RPC::call('movim_fill', 'gallery', $this->prepareGallery($embed));
RPC::call('movim_fill', 'preview', '');
} else {
}
if($embed->type !== 'photo') {
RPC::call('movim_fill', 'preview', $html);
RPC::call('movim_fill', 'gallery', '');
}
} catch(Exception $e) {
error_log($e->getMessage());
@ -253,8 +279,8 @@ class Publish extends WidgetBase
private function validateServerNode($server, $node)
{
$validate_server = Validator::string()->noWhitespace()->length(6, 40);
$validate_node = Validator::string()->length(3, 100);
$validate_server = Validator::stringType()->noWhitespace()->length(6, 40);
$validate_node = Validator::stringType()->length(3, 100);
if(!$validate_server->validate($server)
|| !$validate_node->validate($node)

View file

@ -28,7 +28,7 @@
</article>
<div id="gallery"></div>
</div>
<div id="enable_content" onclick="Publish.enableContent();">
<input type="text" value="{$c->__('publish.add_text')}"/>
<label>{$c->__('publish.add_text_label')}</label>
@ -48,4 +48,18 @@
</li>
{/if}
</ul>
<div>
{if="$item != false"}
{$tags = $item->getTagsImploded()}
{/if}
<input
type="text"
name="tags"
placeholder="write, comma separated, tags"
{if="isset($tags)"}
value="{$tags}"
{/if}>
<label for="title">{$c->__('post.tags')}</label>
</div>
</form>

View file

@ -1,12 +1,12 @@
<div class="quote" cite="{$embed->url}">
<div class="quote" cite="{$embed->url|htmlspecialchars}">
<ul>
<li>
<span>
<a href="{$embed->url|htmlspecialchars}" target="_blank">{$embed->title}</a>
<a href="{$embed->url|htmlspecialchars}" target="_blank">{$embed->title|htmlspecialchars}</a>
</span>
<p>{$embed->description}</p>
<p>{$embed->description|htmlspecialchars}</p>
<p>
<a href="{$embed->providerUrl|htmlspecialchars}" target="_blank">{$embed->providerName}</a>
<a href="{$embed->providerUrl|htmlspecialchars}" target="_blank">{$embed->providerName|htmlspecialchars}</a>
</p>
</li>
{if="$embed->images != null"}

View file

@ -6,7 +6,7 @@
<div class="return active r3 condensed"
onclick="Publish.headerBack('{$server}', '{$node}', false)">
<span id="back" class="icon" ><i class="zmdi zmdi-arrow-back"></i></span>
{if="$item != false"}
{if="$post != false"}
<h2>{$c->__('publish.edit')}</h2>
{else}
<h2>{$c->__('publish.new')}</h2>

View file

@ -203,9 +203,9 @@ class Rooms extends WidgetBase
array_push($arr,
array(
'type' => 'conference',
'name' => htmlentities($c->name),
'name' => $c->name,
'autojoin' => $c->autojoin,
'nick' => htmlentities($c->nick),
'nick' => $c->nick,
'jid' => $c->conference));
}
@ -248,7 +248,7 @@ class Rooms extends WidgetBase
$list = $cod->getAll();
$connected = array();
foreach($list as $key => $room) {
if($this->checkConnected($room->conference, $room->nick)) {
$room->connected = true;
@ -258,7 +258,7 @@ class Rooms extends WidgetBase
}
$list = array_merge($connected, $list);
$view->assign('conferences', $list);
$view->assign('room', $this->get('r'));
@ -272,7 +272,7 @@ class Rooms extends WidgetBase
*/
private function validateRoom($room)
{
$validate_server = Validator::string()->noWhitespace()->length(6, 80);
$validate_server = Validator::stringType()->noWhitespace()->length(6, 80);
if(!$validate_server->validate($room)) return false;
else return true;
}
@ -284,7 +284,7 @@ class Rooms extends WidgetBase
*/
private function validateResource($resource)
{
$validate_resource = Validator::string()->length(2, 40);
$validate_resource = Validator::stringType()->length(2, 40);
if(!$validate_resource->validate($resource)) return false;
else return true;
}

View file

@ -144,9 +144,9 @@ class Vcard4 extends WidgetBase
$c->date = $vcard->date->value;
}
if(Validator::string()->length(0, 40)->validate($vcard->name->value))
if(Validator::stringType()->length(0, 40)->validate($vcard->name->value))
$c->name = $vcard->name->value;
if(Validator::string()->length(0, 40)->validate($vcard->fn->value))
if(Validator::stringType()->length(0, 40)->validate($vcard->fn->value))
$c->fn = $vcard->fn->value;
if(Validator::url()->validate($vcard->url->value))
@ -167,7 +167,7 @@ class Vcard4 extends WidgetBase
$c->skype = $vcard->skype->value;
$c->yahoo = $vcard->yahoo->value;
if(Validator::string()->validate($vcard->desc->value))
if(Validator::stringType()->validate($vcard->desc->value))
$c->description = trim($vcard->desc->value);
$cd = new \Modl\ContactDAO();

View file

@ -316,6 +316,7 @@ class Bootstrap {
Modl\Utils::loadModel('Message');
Modl\Utils::loadModel('Sessionx');
Modl\Utils::loadModel('Conference');
Modl\Utils::loadModel('Tag');
if(file_exists(DOCUMENT_ROOT.'/config/db.inc.php')) {
require DOCUMENT_ROOT.'/config/db.inc.php';

View file

@ -12,7 +12,7 @@
"michelf/php-markdown": "1.4.*@dev",
"movim/modl": "dev-master",
"movim/sasl2": "dev-master",
"movim/moxl": "dev-ws",
"movim/moxl": "dev-master",
"embed/embed": "dev-master",
"heyupdate/emoji": "0.2.*@dev",
@ -22,7 +22,7 @@
"react/socket-client": "0.4.3",
"forxer/Gravatar": "~1.2",
"respect/validation": "0.8.*",
"respect/validation": "1.0.*",
"ezyang/htmlpurifier": "^4.7"
}
}

View file

@ -281,7 +281,7 @@ class XMPPtoForm{
$opt->setAttribute('value', $option->value);
if(
in_array(
(string)$opt->nodeValue,
(string)$option->value,
array_map(
function($sxml) {
return (string)$sxml;
@ -297,8 +297,9 @@ class XMPPtoForm{
}
else{
foreach($s->value as $option){
$label = $option['label'];
$option = $this->html->createElement('option', $option);
$option->setAttribute('value', $option['label']);
$option->setAttribute('value', $label);
$option->setAttribute('selected', 'selected');
$select->appendChild($option);
}

View file

@ -6,6 +6,8 @@ require_once(DOCUMENT_ROOT.'/bootstrap.php');
gc_enable();
//memprof_enable();
$bootstrap = new Bootstrap();
$booted = $bootstrap->boot();
@ -99,6 +101,7 @@ $xmpp_behaviour = function (React\Stream\Stream $stream) use (&$conn, $loop, &$s
$stdin->on('data', $stdin_behaviour);
// We define a huge buffer to prevent issues with SSL streams, see https://bugs.php.net/bug.php?id=65137
$conn->bufferSize = 1024*32;
$conn->on('data', function($message) use (&$conn, $loop, $parser) {
if(!empty($message)) {
$restart = false;
@ -136,14 +139,10 @@ $xmpp_behaviour = function (React\Stream\Stream $stream) use (&$conn, $loop, &$s
\Moxl\API::clear();
\RPC::clear();
fwrite(STDERR, colorize(getenv('sid'), 'yellow')." before : ".\sizeToCleanSize(memory_get_usage())."\n");
if(!$parser->parse($message)) {
fwrite(STDERR, colorize(getenv('sid'), 'yellow')." ".$parser->getError()."\n");
}
fwrite(STDERR, colorize(getenv('sid'), 'yellow')." after : ".\sizeToCleanSize(memory_get_usage())."\n");
if($restart) {
$session = \Sessionx::start();
\Moxl\Stanza\Stream::init($session->host);
@ -170,7 +169,11 @@ $xmpp_behaviour = function (React\Stream\Stream $stream) use (&$conn, $loop, &$s
\Moxl\API::clear();
$loop->tick();
gc_collect_cycles();
//fwrite(STDERR, colorize(getenv('sid'), 'yellow')." end data : ".\sizeToCleanSize(memory_get_usage())."\n");
//memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w"));
}
});
@ -188,6 +191,8 @@ $xmpp_behaviour = function (React\Stream\Stream $stream) use (&$conn, $loop, &$s
$obj = new \StdClass;
$obj->func = 'registered';
fwrite(STDERR, 'registered');
//fwrite(STDERR, colorize(json_encode($obj).' '.strlen($obj), 'yellow')." : ".colorize('obj sent to browser', 'green')."\n");
echo base64_encode(gzcompress(json_encode($obj), 9))."";

View file

@ -31,6 +31,7 @@ visio = Visio-conference
pods = Pods
share = Share
room = Room
tag = Tag
[error]
error = Error: %s

View file

@ -10,10 +10,12 @@ class Core implements MessageComponentInterface {
public $loop;
public $baseuri;
private $cleanerdelay = 60; // in minutes
private $cleanerdelay = 2; // in hours
public function __construct($loop, $baseuri, $port)
{
$baseuri = rtrim($baseuri, '/') . '/';
echo colorize("Movim daemon launched\n", 'green');
echo colorize("Base URI :", 'green')." {$baseuri}\n";
$ws = $this->setWebsocket($baseuri, $port);
@ -110,7 +112,9 @@ class Core implements MessageComponentInterface {
{
$this->loop->addPeriodicTimer(5, function() {
foreach($this->sessions as $sid => $session) {
if(time()-$session->timestamp > $this->cleanerdelay*60) {
if((time()-$session->timestamp > $this->cleanerdelay*3600)
|| ($session->countClients() == 0
&& $session->registered == null)) {
$session->killLinker();
$this->closeEmptySession($sid);
}
@ -122,7 +126,7 @@ class Core implements MessageComponentInterface {
{
// No WebSockets and no linker ? We close the whole session
if($this->sessions[$sid]->countClients() == 0
&& $this->sessions[$sid]->process == null) {
&& ($this->sessions[$sid]->process == null)) {
$sd = new \Modl\SessionxDAO();
$sd->delete($sid);

View file

@ -10,6 +10,8 @@ class Session {
protected $baseuri;
public $process;
public $registered;
protected $buffer;
public function __construct($loop, $sid, $baseuri)
@ -77,9 +79,15 @@ class Session {
$sd->delete($this->sid);
});
$self = $this;
// Debug only, if the linker output some errors
$this->process->stderr->on('data', function($output) use ($me) {
echo $output;
$this->process->stderr->on('data', function($output) use ($me, $self) {
if(strpos($output, 'registered') !== false) {
$self->registered = true;
} else {
echo $output;
}
});
}

View file

@ -81,7 +81,13 @@ class Locale {
&& array_key_exists($arr[1], $this->hash[$arr[0]])) {
$skey = $this->hash[$arr[0]][$arr[1]];
if(is_array($this->translations)
if($this->language == 'en') {
if(is_string($skey)) {
$string = $skey;
} else {
$string = $skey[0];
}
} elseif(is_array($this->translations)
&& array_key_exists($skey, $this->translations)
&& isset($this->translations[$skey])) {
$string = $this->translations[$skey];

View file

@ -10,12 +10,13 @@ class Route extends \BaseController {
'accountnext' => array('s', 'err'),
'admin' => false,
'blog' => array('f', 'i'),
'tag' => array('t', 'i'),
'chat' => array('f'),
'conf' => false,
'contact' => array('f'),
'disconnect' => array('err'),
'feed' => array('s', 'n'),
'grouppublic' => array('s', 'n', 'i'),
'node' => array('s', 'n', 'i'),
'group' => array('s', 'n', 'i'),
'help' => false,
'infos' => false,
@ -34,7 +35,8 @@ class Route extends \BaseController {
public function find() {
$this->fix($_GET, $_SERVER['QUERY_STRING']);
$uri = reset(array_keys($_GET));
$gets = array_keys($_GET);
$uri = reset($gets);
unset($_GET[$uri]);
$request = explode('/', $uri);

View file

@ -15,8 +15,6 @@
* See COPYING for licensing information.
*/
class User {
private $xmppSession;
public $username = '';
private $password = '';
private $config = array();
@ -32,12 +30,18 @@ class User {
* Class constructor. Reloads the user's session or attempts to authenticate
* the user.
*/
function __construct()
function __construct($username = false)
{
$session = \Sessionx::start();
if($session->active) {
$this->username = $session->user.'@'.$session->host;
if($username) {
$this->username = $username;
}
$session = \Sessionx::start();
if($session->active && $this->username == null) {
$this->username = $session->user.'@'.$session->host;
}
if($this->username != null) {
$this->userdir = DOCUMENT_ROOT.'/users/'.$this->username.'/';
$this->useruri = BASE_URI.'users/'.$this->username.'/';
}
@ -157,6 +161,9 @@ class User {
{
$session = \Sessionx::start();
$session->config = $config;
file_put_contents($this->userdir.'config.dump', serialize($config));
$this->reload();
}
@ -168,6 +175,16 @@ class User {
return $this->config[$key];
}
function getDumpedConfig($key = false)
{
$config = unserialize(file_get_contents($this->userdir.'config.dump'));
if($key == false)
return $config;
if(isset($config[$key]))
return $config[$key];
}
function isSupported($key)
{
$this->reload();

View file

@ -636,11 +636,9 @@ function requestURL($url, $timeout = 10, $post = false) {
/*
* @desc Get the URI of a smiley
*/
function getSmileyPath($id, $large = true)
function getSmileyPath($id)
{
$folder = '';
if($large) $folder = 'large/';
return BASE_URI.'/themes/material/img/emojis/'.$folder.$id.'.png';
return BASE_URI.'/themes/material/img/emojis/svg/'.$id.'.svg';
}
/*

View file

@ -2,15 +2,22 @@
function createEmailPic($jid, $email) {
if(file_exists(DOCUMENT_ROOT.'/cache/'.$jid.'_email.jpg'))
unlink(DOCUMENT_ROOT.'/cache/'.$jid.'_email.jpg');
$thumb = imagecreatetruecolor(250, 20);
$white = imagecolorallocate($thumb, 255, 255, 255);
imagefill($thumb, 0, 0, $white);
$cachefile = DOCUMENT_ROOT.'/cache/'.$jid.'_email.png';
$text_color = imagecolorallocate ($thumb, 0, 0,0);//black text
imagestring ($thumb, 4, 0, 0, $email, $text_color);
imagejpeg($thumb, DOCUMENT_ROOT.'/cache/'.$jid.'_email.jpg', 95);
if(file_exists(DOCUMENT_ROOT.'/cache/'.$jid.'_email.png'))
unlink(DOCUMENT_ROOT.'/cache/'.$jid.'_email.png');
$draw = new ImagickDraw();
$draw->setFontSize(13);
$draw->setGravity(Imagick::GRAVITY_CENTER);
$canvas = new Imagick();
$metrics = $canvas->queryFontMetrics($draw, $email);
$canvas->newImage($metrics['textWidth'], $metrics['textHeight'], "transparent", "png");
$canvas->annotateImage($draw, 0, 0, 0, $email);
$canvas->setImageFormat('PNG');
$canvas->writeImage($cachefile);
}

View file

@ -39,7 +39,7 @@ class AjaxController extends BaseController
}
$buffer = '<script type="text/javascript">';
foreach($this->funclist as $funcdef) {
foreach($this->funclist as $key => $funcdef) {
$parlist = implode(', ', $funcdef['params']);
$buffer .= "function " . $funcdef['object'] . '_'
@ -54,7 +54,7 @@ class AjaxController extends BaseController
*/
public function defun($widget, $funcname, array $params)
{
$this->funclist[] = array(
$this->funclist[$widget.$funcname] = array(
'object' => $widget,
'funcname' => $funcname,
'params' => $params,

View file

@ -30,7 +30,7 @@ class FrontController extends BaseController
else {
$log = new Logger('movim');
$log->pushHandler(new SyslogHandler('movim'));
$log->addError(t("Requested controller '%s' doesn't exist.", $class_name));
$log->addError(__("Requested controller '%s' doesn't exist.", $class_name));
exit;
}

View file

@ -99,9 +99,97 @@ class TplPageBuilder
*/
function title()
{
$widgets = WidgetWrapper::getInstance();
if(isset($widgets->title)) {
$this->title .= ' - ' . $widgets->title;
}
echo $this->title;
}
/**
* Display some meta tag defined in the widgets using Facebook OpenGraph
*/
function meta()
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$metas = $dom->createElement('xml');
$dom->appendChild($metas);
$widgets = WidgetWrapper::getInstance();
if(isset($widgets->title)) {
$meta = $dom->createElement('meta');
$meta->setAttribute('property', 'og:title');
$meta->setAttribute('content', $widgets->title);
$metas->appendChild($meta);
$meta = $dom->createElement('meta');
$meta->setAttribute('name', 'twitter:title');
$meta->setAttribute('content', $widgets->title);
$metas->appendChild($meta);
}
if(isset($widgets->image)) {
$meta = $dom->createElement('meta');
$meta->setAttribute('property', 'og:image');
$meta->setAttribute('content', $widgets->image);
$metas->appendChild($meta);
$meta = $dom->createElement('meta');
$meta->setAttribute('name', 'twitter:image');
$meta->setAttribute('content', $widgets->image);
$metas->appendChild($meta);
}
if(isset($widgets->description)) {
$meta = $dom->createElement('meta');
$meta->setAttribute('property', 'og:description');
$meta->setAttribute('content', $widgets->description);
$metas->appendChild($meta);
$meta = $dom->createElement('meta');
$meta->setAttribute('name', 'twitter:description');
$meta->setAttribute('content', $widgets->description);
$metas->appendChild($meta);
$meta = $dom->createElement('meta');
$meta->setAttribute('name', 'description');
$meta->setAttribute('content', $widgets->description);
$metas->appendChild($meta);
} else {
$cd = new \Modl\ConfigDAO();
$config = $cd->get();
$meta = $dom->createElement('meta');
$meta->setAttribute('name', 'description');
$meta->setAttribute('content', $config->description);
$metas->appendChild($meta);
}
if(isset($widgets->url)) {
$meta = $dom->createElement('meta');
$meta->setAttribute('property', 'og:url');
$meta->setAttribute('content', $widgets->url);
$metas->appendChild($meta);
}
$meta = $dom->createElement('meta');
$meta->setAttribute('property', 'og:type');
$meta->setAttribute('content', 'article');
$metas->appendChild($meta);
$meta = $dom->createElement('meta');
$meta->setAttribute('property', 'twitter:card');
$meta->setAttribute('content', 'summary_large_image');
$metas->appendChild($meta);
$meta = $dom->createElement('meta');
$meta->setAttribute('property', 'twitter:site');
$meta->setAttribute('content', 'MovimNetwork');
$metas->appendChild($meta);
echo strip_tags($dom->saveXML($dom->documentElement), '<meta>');
}
function addScript($script)
{
$this->scripts[] = BASE_URI . 'app/assets/js/' . $script;
@ -168,9 +256,4 @@ class TplPageBuilder
echo $widgets->runWidget($name, 'build');
}
function displayFooterDebug()
{
//\system\Logs\Logger::displayFooterDebug();
}
}

View file

@ -22,6 +22,7 @@ class WidgetBase
{
protected $js = array(); /*< Contains javascripts. */
protected $css = array(); /*< Contains CSS files. */
protected $rawcss = array(); /*< Contains raw CSS files links. */
protected $ajax; /*< Contains ajax client code. */
protected $user;
protected $name;
@ -31,6 +32,11 @@ class WidgetBase
public $events;
public $filters;
// Meta tags
public $title;
public $image;
public $description;
/**
* Initialises Widget stuff.
*/
@ -38,6 +44,8 @@ class WidgetBase
{
if($view != null) $this->_view = $view;
$this->user = new User;
$this->load();
$this->name = get_class($this);
@ -48,10 +56,8 @@ class WidgetBase
// Put default widget init here.
$this->ajax = AjaxController::getInstance();
$this->user = new User;
// Generating Ajax calls.
$refl = new ReflectionClass(get_class($this));
$refl = new ReflectionClass($this->name);
$meths = $refl->getMethods();
foreach($meths as $method) {
@ -62,7 +68,7 @@ class WidgetBase
$params[] = $param->name;
}
$this->ajax->defun(get_class($this), $method->name, $params);
$this->ajax->defun($this->name, $method->name, $params);
}
}
@ -84,7 +90,9 @@ class WidgetBase
function __destruct()
{
unset($this->view);
unset($this->ajax);
unset($this->user);
unset($this->_view);
}
function __()
@ -238,19 +246,27 @@ class WidgetBase
}
/**
* @brief Adds a javascript file to this widget.
* @brief Adds a CSS file to this widget.
*/
protected function addcss($filename)
{
$this->css[] = $this->respath($filename);
}
/**
* @brief Adds a CSS to the page.
*/
protected function addrawcss($url)
{
$this->rawcss[] = $url;
}
/**
* @brief returns the list of javascript files to be loaded for the widget.
*/
public function loadcss()
{
return $this->css;
return array_merge($this->css, $this->rawcss);
}
/*

View file

@ -32,6 +32,11 @@ class WidgetWrapper
private $css = array(); // All the css loaded by the widgets so far.
private $js = array(); // All the js loaded by the widgets so far.
public $title = null; // If a widget has defined a particular title
public $image = null; // If a widget has defined a particular image
public $description = null; // If a widget has defined a particular description
public $url = null; // If a widget has defined a particular url
private function __construct()
{
}
@ -107,7 +112,6 @@ class WidgetWrapper
}
}
}
unset($widget);
} else {
if($this->_view != '') {
$widget = new $name(false, $this->_view);
@ -118,6 +122,11 @@ class WidgetWrapper
$this->css = array_merge($this->css, $widget->loadcss());
$this->js = array_merge($this->js, $widget->loadjs());
if(isset($widget->title)) $this->title = $widget->title;
if(isset($widget->image)) $this->image = $widget->image;
if(isset($widget->description)) $this->description = $widget->description;
if(isset($widget->url)) $this->url = $widget->url;
return $widget;
}
}
@ -140,8 +149,6 @@ class WidgetWrapper
$result = call_user_func_array(array($widget, $method), $params);
unset($widget, $method, $params);
return $result;
}
@ -156,7 +163,7 @@ class WidgetWrapper
{
if(array_key_exists($key, $this->_events)) {
foreach($this->_events[$key] as $widget_name) {
$widget = new $widget_name;
$widget = new $widget_name(true);
if(array_key_exists($key, $widget->events)) {
foreach($widget->events[$key] as $method) {
/*
@ -177,17 +184,13 @@ class WidgetWrapper
$widget->{$method}($data);
}
}
unset($session, $notifs_key);
} else {
$widget->{$method}($data);
}
}
}
unset($widget);
}
}
unset($key, $data);
}
/**

View file

@ -142,6 +142,21 @@ article section content img.big_picture {
margin-bottom: 1rem;
}
article section content div.video_embed {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
margin-bottom: 2rem;
height: 0;
}
article section content div.video_embed iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
article ul li.pic img {
max-width: 30rem;
max-height: 30rem;

View file

@ -28,3 +28,20 @@
font-weight: 800;
src: local('Open Sans Extrabold'), local('OpenSans-Extrabold'), url(../fonts/os_800.woff2) format('woff2'), url(../fonts/os_800.woff) format('woff');
}
.emoji {
width: 2rem;
height: 2rem;
margin: 0 0.5rem;
margin-bottom: -0.3rem;
}
.emoji.large {
width: 5rem;
height: 5rem;
margin: 0;
}
.hfr {
display: inline-block;
}

View file

@ -6,6 +6,10 @@ form > div:not(.clear):not(.control) {
box-sizing: border-box;
}
form > div.compact:not(.clear):not(.control) {
min-height: 0;
}
li > form > div:not(.control) { /* If we put the form in a list */
min-height: 0;
line-height: 3rem;
@ -60,6 +64,7 @@ form > div > .select:after {
form > div > .select select {
width: calc(100% + 3rem);
background-color: transparent;
background-image: none;
}
main > header form > div:not(.clear):not(.control) {
@ -106,6 +111,12 @@ form > div > textarea {
box-shadow: none; /* Firefox weird CSS */
}
form > div.compact > .select,
form > div.compact > input:not([type=submit]),
form > div.compact > textarea {
padding-top: 2.5rem;
}
/* Webkit hack */
form > div > input:not([type=submit]):-webkit-autofill {
-webkit-box-shadow: 0 0 0 50px white inset;
@ -261,6 +272,8 @@ input[type=button] {
transition: background 0.3s ease, box-shadow 0.3s ease;
box-shadow: 0 0.1rem 0.3rem rgba(0, 0, 0, 0.5);
background-image: none;
}
.button:active {

View file

@ -1,5 +1,5 @@
/* Grid */
ul.grid li {
ul.grid > li {
background-size: cover;
width: calc(25% - 0.2em);
padding: 0;
@ -12,7 +12,7 @@ ul.grid li {
margin: 0.1em;
}
ul.grid nav {
ul.grid > li > nav {
position: absolute;
bottom: 0;
color: white;
@ -26,14 +26,14 @@ ul.grid nav {
}
@media screen and (max-width: 1024px) {
ul.grid li {
ul.grid > li {
width: calc(33.33% - 0.2em);
padding-bottom: 33.33%;
}
}
@media screen and (max-width: 640px) {
ul.grid li {
ul.grid > li {
width: calc(50% - 0.2em);
padding-bottom: 50%;
}
@ -44,3 +44,7 @@ ul.grid:after {
display: block;
clear: both;
}
ul.grid.padded {
padding: 0;
}

File diff suppressed because one or more lines are too long

View file

@ -811,12 +811,10 @@ main section > div:first-child:nth-last-child(2) ~ div .actions.fixed > div:last
.icon.news { background-image: url(../img/icons/receipt.svg); }
.icon.forum { background-image: url(../img/icons/forum.svg); }
.icon.contacts { background-image: url(../img/icons/group.svg); }
.icon.media { background-image: url(../img/placeholder/media.png); }
.icon.explore { background-image: url(../img/placeholder/explore.png); }
.icon.plane { background-image: url(../img/placeholder/plane.png); }
.icon.file { background-image: url(../img/placeholder/file.png); }
.icon.account { background-image: url(../img/icons/perm_identity.svg); }
.icon.pages { background-image: url(../img/icons/pages.svg); }
.icon.clipboard { background-image: url(../img/icons/assignment_turned_in.svg); }
.icon.bookmark { background-image: url(../img/icons/bookmark.svg); }
.icon.clipboard { background-image: url(../img/icons/person.svg); }
/* Definition list */

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 237 KiB

After

Width:  |  Height:  |  Size: 234 KiB

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