mirror of https://github.com/movim/movim
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
11 KiB
327 lines
11 KiB
<?php
|
|
|
|
namespace App;
|
|
|
|
use Movim\Model;
|
|
use Movim\Picture;
|
|
|
|
class Message extends Model
|
|
{
|
|
protected $primaryKey = ['user_id', 'jidfrom', 'id'];
|
|
public $incrementing = false;
|
|
|
|
protected $guarded = [];
|
|
|
|
protected $attributes = [
|
|
'type' => 'chat'
|
|
];
|
|
|
|
protected $casts = [
|
|
'edited' => 'boolean',
|
|
'quoted' => 'boolean',
|
|
'markable' => 'boolean'
|
|
];
|
|
|
|
public function save(array $options = [])
|
|
{
|
|
try {
|
|
parent::save($options);
|
|
} catch (\Exception $e) {
|
|
// Race condition
|
|
}
|
|
}
|
|
|
|
public function user()
|
|
{
|
|
return $this->belongsTo('App\User');
|
|
}
|
|
|
|
public function setFileAttribute(array $file)
|
|
{
|
|
$this->attributes['file'] = serialize($file);
|
|
}
|
|
|
|
public function getFileAttribute()
|
|
{
|
|
if (isset($this->attributes['file'])) {
|
|
$file = unserialize($this->attributes['file']);
|
|
$file['cleansize'] = sizeToCleanSize($file['size']);
|
|
return $file;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static function findByStanza($stanza)
|
|
{
|
|
/**
|
|
* If this stanza replaces another one, we load the original message
|
|
*/
|
|
if ($stanza->replace) {
|
|
return self::firstOrNew([
|
|
'user_id' => \App\User::me()->id,
|
|
'replaceid' => (string)$stanza->replace->attributes()->id,
|
|
'jidfrom' => current(explode('/',(string)$stanza->attributes()->from))
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* If not we just create or load a message
|
|
*/
|
|
$id = ($stanza->{'stanza-id'} && $stanza->{'stanza-id'}->attributes()->id)
|
|
? (string)$stanza->{'stanza-id'}->attributes()->id
|
|
: 'm_' . generateUUID();
|
|
|
|
return self::firstOrNew([
|
|
'user_id' => \App\User::me()->id,
|
|
'id' => $id,
|
|
'jidfrom' => current(explode('/',(string)$stanza->attributes()->from))
|
|
]);
|
|
}
|
|
|
|
public function set($stanza, $parent = false)
|
|
{
|
|
$this->id = ($stanza->{'stanza-id'} && $stanza->{'stanza-id'}->attributes()->id)
|
|
? (string)$stanza->{'stanza-id'}->attributes()->id
|
|
: 'm_' . generateUUID();
|
|
|
|
if ($stanza->attributes()->id) {
|
|
$this->replaceid = $stanza->attributes()->id;
|
|
}
|
|
|
|
$jid = explode('/',(string)$stanza->attributes()->from);
|
|
$to = current(explode('/',(string)$stanza->attributes()->to));
|
|
|
|
$this->user_id = \App\User::me()->id;
|
|
|
|
if (!$this->jidto) {
|
|
$this->jidto = $to;
|
|
}
|
|
|
|
if (!$this->jidfrom) {
|
|
$this->jidfrom = $jid[0];
|
|
}
|
|
|
|
if (isset($jid[1])) {
|
|
$this->resource = $jid[1];
|
|
}
|
|
|
|
if ($stanza->delay) {
|
|
$this->published = gmdate('Y-m-d H:i:s', strtotime($stanza->delay->attributes()->stamp));
|
|
} elseif ($parent && $parent->delay) {
|
|
$this->published = gmdate('Y-m-d H:i:s', strtotime($parent->delay->attributes()->stamp));
|
|
} elseif (!isset($stanza->replace)) {
|
|
$this->published = gmdate('Y-m-d H:i:s');
|
|
}
|
|
|
|
if ($stanza->body || $stanza->subject) {
|
|
$this->type = 'chat';
|
|
if ($stanza->attributes()->type) {
|
|
$this->type = (string)$stanza->attributes()->type;
|
|
}
|
|
|
|
/*if (isset($stanza->attributes()->id)) {
|
|
$this->id = (string)$stanza->attributes()->id;
|
|
}*/
|
|
|
|
if ($stanza->x
|
|
&& (string)$stanza->x->attributes()->xmlns == 'http://jabber.org/protocol/muc#user'
|
|
&& isset($jid[1])) {
|
|
$this->jidfrom = $jid[0].'/'.$jid[1];
|
|
}
|
|
|
|
if ($stanza->body) {
|
|
$this->body = (string)$stanza->body;
|
|
}
|
|
|
|
# HipChat MUC specific cards
|
|
if (in_array(
|
|
explodeJid($this->jidfrom)['server'],
|
|
['conf.hipchat.com', 'conf.btf.hipchat.com']
|
|
)
|
|
&& $this->type == 'groupchat'
|
|
&& $stanza->x
|
|
&& $stanza->x->attributes()->xmlns == 'http://hipchat.com/protocol/muc#room'
|
|
&& $stanza->x->card) {
|
|
$this->body = trim(html_entity_decode($this->body));
|
|
}
|
|
|
|
$this->markable = (bool)($stanza->markable);
|
|
|
|
if ($stanza->subject) {
|
|
$this->subject = (string)$stanza->subject;
|
|
}
|
|
|
|
if ($stanza->thread) {
|
|
$this->thread = (string)$stanza->thread;
|
|
}
|
|
|
|
if ($this->type == 'groupchat') {
|
|
$presence = $this->user->session->presences()
|
|
->where('jid', $this->jidfrom)
|
|
->where('mucjid', $this->user->id)
|
|
->first();
|
|
|
|
if ($presence
|
|
&& strpos($this->body, $presence->resource) !== false
|
|
&& $this->resource != $presence->resource) {
|
|
$this->quoted = true;
|
|
}
|
|
}
|
|
|
|
if ($stanza->html) {
|
|
$results = [];
|
|
|
|
$xml = \simplexml_load_string((string)$stanza->html);
|
|
if (!$xml) {
|
|
$xml = \simplexml_load_string((string)$stanza->html->body);
|
|
if ($xml) {
|
|
$results = $xml->xpath('//img/@src');
|
|
}
|
|
} else {
|
|
$xml->registerXPathNamespace('xhtml', 'http://www.w3.org/1999/xhtml');
|
|
$results = $xml->xpath('//xhtml:img/@src');
|
|
}
|
|
|
|
if (!empty($results)) {
|
|
if (substr((string)$results[0], 0, 10) == 'data:image') {
|
|
$str = explode('base64,', $results[0]);
|
|
if (isset($str[1])) {
|
|
$p = new Picture;
|
|
$p->fromBase(urldecode($str[1]));
|
|
$key = sha1(urldecode($str[1]));
|
|
$p->set($key, 'png');
|
|
|
|
$this->sticker = $key;
|
|
}
|
|
} else {
|
|
$this->sticker = getCid((string)$results[0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($stanza->reference) {
|
|
$filetmp = [];
|
|
|
|
if ($stanza->reference->{'media-sharing'}) {
|
|
$file = $stanza->reference->{'media-sharing'}->file;
|
|
if (isset($file)) {
|
|
if (preg_match('/\w+\/[-+.\w]+/', $file->{'media-type'}) == 1) {
|
|
$filetmp['type'] = (string)$file->{'media-type'};
|
|
}
|
|
$filetmp['size'] = (int)$file->size;
|
|
$filetmp['name'] = (string)$file->name;
|
|
}
|
|
|
|
if ($stanza->reference->{'media-sharing'}->sources) {
|
|
$source = $stanza->reference->{'media-sharing'}->sources->reference;
|
|
|
|
if (!filter_var((string)$source->attributes()->uri, FILTER_VALIDATE_URL) === false) {
|
|
$filetmp['uri'] = (string)$source->attributes()->uri;
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('uri', $filetmp)
|
|
&& array_key_exists('type', $filetmp)
|
|
&& array_key_exists('size', $filetmp)
|
|
&& array_key_exists('name', $filetmp)) {
|
|
$this->file = $filetmp;
|
|
}
|
|
} elseif ($stanza->reference->attributes()->type == 'mention'
|
|
&& parse_url($stanza->reference->attributes()->uri !== false)) {
|
|
$begin = '<a href="' . Route::urlize('share', $stanza->reference->attributes()->uri) . '">';
|
|
|
|
$this->html = substr_replace(
|
|
$this->body,
|
|
$begin,
|
|
(int)$stanza->reference->attributes()->begin,
|
|
0
|
|
);
|
|
$this->html = substr_replace(
|
|
$this->html,
|
|
'</a>',
|
|
(int)$stanza->reference->attributes()->end + strlen($begin),
|
|
0
|
|
);
|
|
}
|
|
}
|
|
|
|
if ($stanza->replace
|
|
&& $this->user->messages()
|
|
->where('jidfrom', $this->jidfrom)
|
|
->where('replaceid', $this->replaceid)
|
|
->count() == 0
|
|
) {
|
|
$message = $this->user->messages()
|
|
->where('jidfrom', $this->jidfrom)
|
|
->where('replaceid', (string)$stanza->replace->attributes()->id)
|
|
->first();
|
|
$this->oldid = $message->id;
|
|
$this->edited = true;
|
|
|
|
/**
|
|
* We prepare the existing message to be edited in the DB
|
|
*/
|
|
Message::where('replaceid', (string)$stanza->replace->attributes()->id)
|
|
->where('user_id', $this->user_id)
|
|
->where('jidfrom', $this->jidfrom)
|
|
->update(['id' => $this->id]);
|
|
}
|
|
|
|
if (isset($stanza->x->invite)) {
|
|
$this->type = 'invitation';
|
|
$this->subject = $this->jidfrom;
|
|
$this->jidfrom = current(explode('/',(string)$stanza->x->invite->attributes()->from));
|
|
}
|
|
|
|
//return $this->checkPicture();
|
|
} elseif (isset($stanza->x)
|
|
&& $stanza->x->attributes()->xmlns == 'jabber:x:conference') {
|
|
$this->type = 'invitation';
|
|
$this->body = (string)$stanza->x->attributes()->reason;
|
|
$this->subject = (string)$stanza->x->attributes()->jid;
|
|
}
|
|
}
|
|
|
|
public function convertEmojis()
|
|
{
|
|
$emoji = \Movim\Emoji::getInstance();
|
|
$this->body = addHFR($emoji->replace($this->body));
|
|
}
|
|
|
|
public function isTrusted()
|
|
{
|
|
/*$rd = new \Modl\RosterLinkDAO;
|
|
$from = explode('@', cleanJid((string)$this->jidfrom));
|
|
$from = explode('.', end($from));
|
|
|
|
$session = explode('@',(string)$this->session);
|
|
|
|
return ($this->session == $this->jidfrom
|
|
|| end($session) == $from[count($from)-2].'.'.$from[count($from)-1]
|
|
|| $rd->get($this->jidfrom) !== null);*/
|
|
}
|
|
|
|
public function isEmpty()
|
|
{
|
|
return (empty($this->body)
|
|
&& empty($this->picture)
|
|
&& empty($this->sticker)
|
|
);
|
|
}
|
|
|
|
public function isSubject()
|
|
{
|
|
return !empty($this->subject);
|
|
}
|
|
|
|
public function isOTR()
|
|
{
|
|
return preg_match('#^\?OTR#', $this->body);
|
|
}
|
|
|
|
public function addUrls()
|
|
{
|
|
$this->body = addUrls($this->body);
|
|
}
|
|
}
|