File indexing completed on 2024-05-26 05:59:17

0001 <?php
0002 
0003 /**
0004  *  ocs-webserver
0005  *
0006  *  Copyright 2016 by pling GmbH.
0007  *
0008  *    This file is part of ocs-webserver.
0009  *
0010  *    This program is free software: you can redistribute it and/or modify
0011  *    it under the terms of the GNU Affero General Public License as
0012  *    published by the Free Software Foundation, either version 3 of the
0013  *    License, or (at your option) any later version.
0014  *
0015  *    This program is distributed in the hope that it will be useful,
0016  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018  *    GNU Affero General Public License for more details.
0019  *
0020  *    You should have received a copy of the GNU Affero General Public License
0021  *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0022  *
0023  * Created: 19.06.2018
0024  */
0025 class Default_Model_Ocs_Matrix
0026 {
0027     protected $messages;
0028     protected $auth;
0029     private $httpServer;
0030     private $image_mime_types = array(
0031         // images
0032         'png'  => 'image/png',
0033         'jpe'  => 'image/jpeg',
0034         'jpeg' => 'image/jpeg',
0035         'jpg'  => 'image/jpeg',
0036         'gif'  => 'image/gif',
0037         'bmp'  => 'image/bmp',
0038         'ico'  => 'image/vnd.microsoft.icon',
0039         'tiff' => 'image/tiff',
0040         'tif'  => 'image/tiff',
0041         'svg'  => 'image/svg+xml',
0042         'svgz' => 'image/svg+xml'
0043     );
0044 
0045 
0046     /**
0047      * @inheritDoc
0048      */
0049     public function __construct($config = null)
0050     {
0051         if (isset($config)) {
0052             $this->config = $config;
0053         } else {
0054             $this->config = Zend_Registry::get('config')->settings->server->chat;
0055         }
0056         $uri = $this->config->host;
0057         $this->httpServer = new Zend_Http_Client($uri, array('keepalive' => true, 'strictredirects' => true));
0058     }
0059 
0060     public function setAvatarFromArray($member_data)
0061     {
0062         if (empty($member_data)) {
0063             return false;
0064         }
0065 
0066         $this->messages = array();
0067 
0068         try {
0069             $helperImage = new Default_View_Helper_Image();
0070             $memberAvatarUrl = $helperImage->Image($member_data['profile_image_url']);
0071 
0072             list($fileAvatar,$content_type) = $this->fetchAvatarFile($memberAvatarUrl);
0073             $mime_type = $this->checkValidMimeType($content_type) ? $content_type : $this->get_mime_content_type($member_data['profile_image_url']);
0074             $contentUri = $this->uploadAvatar($fileAvatar, $mime_type);
0075             $matrixUserId = $this->generateUserId(strtolower($member_data['username']));
0076             $result = $this->setAvatarUrl($matrixUserId, $contentUri);
0077             if (false === $result) {
0078                 $this->messages[] = "Fail ";
0079 
0080                 return false;
0081             }
0082         } catch (Exception $e) {
0083             $this->messages[] = "Fail : " . $e->getMessage();
0084 
0085             return false;
0086         }
0087         $this->messages[] = "set avatar file : Success";
0088 
0089         return true;
0090     }
0091 
0092     private function fetchAvatarFile($profile_image_url)
0093     {
0094         $http_client = new Zend_Http_Client($profile_image_url);
0095         $response = $http_client->request();
0096         if ($response->getStatus() < 200 OR $response->getStatus() >= 400) {
0097             $this->messages[] = 'Request failed.(' . $profile_image_url . ') OCS Matrix server send message: ' . $response->getBody();
0098 
0099             return false;
0100         }
0101         $filename = IMAGES_UPLOAD_PATH . 'tmp/' . md5($profile_image_url);
0102         file_put_contents($filename, $response->getBody());
0103         $content_type = $response->getHeader('content-type');
0104 
0105         return array($filename,$content_type);
0106     }
0107 
0108     private function get_mime_content_type($filename)
0109     {
0110 
0111         $mime_types = array(
0112 
0113             'txt'  => 'text/plain',
0114             'htm'  => 'text/html',
0115             'html' => 'text/html',
0116             'php'  => 'text/html',
0117             'css'  => 'text/css',
0118             'js'   => 'application/javascript',
0119             'json' => 'application/json',
0120             'xml'  => 'application/xml',
0121             'swf'  => 'application/x-shockwave-flash',
0122             'flv'  => 'video/x-flv',
0123             // images
0124             'png'  => 'image/png',
0125             'jpe'  => 'image/jpeg',
0126             'jpeg' => 'image/jpeg',
0127             'jpg'  => 'image/jpeg',
0128             'gif'  => 'image/gif',
0129             'bmp'  => 'image/bmp',
0130             'ico'  => 'image/vnd.microsoft.icon',
0131             'tiff' => 'image/tiff',
0132             'tif'  => 'image/tiff',
0133             'svg'  => 'image/svg+xml',
0134             'svgz' => 'image/svg+xml',
0135             // archives
0136             'zip'  => 'application/zip',
0137             'rar'  => 'application/x-rar-compressed',
0138             'exe'  => 'application/x-msdownload',
0139             'msi'  => 'application/x-msdownload',
0140             'cab'  => 'application/vnd.ms-cab-compressed',
0141             // audio/video
0142             'mp3'  => 'audio/mpeg',
0143             'qt'   => 'video/quicktime',
0144             'mov'  => 'video/quicktime',
0145             // adobe
0146             'pdf'  => 'application/pdf',
0147             'psd'  => 'image/vnd.adobe.photoshop',
0148             'ai'   => 'application/postscript',
0149             'eps'  => 'application/postscript',
0150             'ps'   => 'application/postscript',
0151             // ms office
0152             'doc'  => 'application/msword',
0153             'rtf'  => 'application/rtf',
0154             'xls'  => 'application/vnd.ms-excel',
0155             'ppt'  => 'application/vnd.ms-powerpoint',
0156             // open office
0157             'odt'  => 'application/vnd.oasis.opendocument.text',
0158             'ods'  => 'application/vnd.oasis.opendocument.spreadsheet',
0159         );
0160 
0161         $filename_parts = explode('.', $filename);
0162         $ext = strtolower(array_pop($filename_parts));
0163         if (array_key_exists($ext, $mime_types)) {
0164             return $mime_types[$ext];
0165         } else if (function_exists('finfo_open')) {
0166             $finfo = finfo_open(FILEINFO_MIME);
0167             $mimetype = finfo_file($finfo, $filename);
0168             finfo_close($finfo);
0169 
0170             return $mimetype;
0171         } else {
0172             return 'image/png';
0173         }
0174     }
0175 
0176     private function checkValidMimeType($mime_type)
0177     {
0178         if (in_array(strtolower($mime_type), $this->image_mime_types)) {
0179             return true;
0180         }
0181 
0182         return false;
0183     }
0184 
0185     private function uploadAvatar($fileAvatar, $mime_type = 'image/png')
0186     {
0187         $auth = $this->authAdmin();
0188 
0189         $filename = basename($fileAvatar);
0190         $uri = $this->config->host . '/_matrix/media/v1/upload?filename=' . $filename;
0191 
0192         $file_data = file_get_contents(realpath($fileAvatar));
0193         $client = new Zend_Http_Client($uri);
0194         $client->setHeaders('Authorization', 'Bearer ' . $auth['access_token']);
0195         $client->setRawData($file_data, $mime_type);
0196 
0197         $response = $client->request('POST');
0198 
0199         if ($response->getStatus() < 200 OR $response->getStatus() >= 400) {
0200             $this->messages[] = 'Request failed.(' . $fileAvatar . ') OCS Matrix server send message: ' . $response->getBody();
0201 
0202             return false;
0203         }
0204 
0205         try {
0206             $body = Zend_Json_Decoder::decode($response->getBody());
0207         } catch (Zend_Json_Exception $e) {
0208             Zend_Registry::get('logger')->err(__METHOD__ . ' - ' . $e->getMessage());
0209 
0210             return false;
0211         }
0212 
0213         return $body['content_uri'];
0214     }
0215 
0216     private function authAdmin()
0217     {
0218         $cache_name = "matrix_auth";
0219         /** @var Zend_Cache_Core $cache */
0220         $cache = Zend_Registry::get('cache');
0221 
0222         if (($result = $cache->load($cache_name))) {
0223             return $result;
0224         }
0225 
0226         $method = Zend_Http_Client::POST;
0227         $uri = $this->config->host . "/_matrix/client/r0/login";
0228         $username = $this->config->sudo_user;
0229         $pw = $this->config->sudo_user_pw;
0230         $data = array(
0231             'identifier'                  => array('type' => 'm.id.user', 'user' => $username),
0232             'initial_device_display_name' => 'ocs webserver',
0233             'password'                    => $pw,
0234             'type'                        => 'm.login.password'
0235         );
0236         try {
0237             $result = $this->httpRequestWithoutToken($uri, $method, $data);
0238         } catch (Exception $e) {
0239             Zend_Registry::get('logger')->err(__METHOD__ . ' - ' . $e->getMessage());
0240         }
0241         $cache->save($result, $cache_name, array());
0242         $this->auth = $result;
0243 
0244         return $result;
0245     }
0246 
0247     private function httpRequestWithoutToken($uri, $method, $post_param)
0248     {
0249         $this->httpServer->resetParameters(true);
0250         $this->httpServer->setUri($uri);
0251         $this->httpServer->setHeaders('Content-Type', 'application/json');
0252         $this->httpServer->setHeaders('Accept', 'application/json');
0253         $this->httpServer->setHeaders('User-Agent', $this->config->user_agent);
0254         $this->httpServer->setMethod($method);
0255         if (isset($post_param)) {
0256             $jsonUserData = Zend_Json::encode($post_param);
0257             $this->httpServer->setRawData($jsonUserData, 'application/json');
0258         }
0259 
0260         $response = $this->httpServer->request();
0261         if ($response->getStatus() < 200 OR $response->getStatus() >= 500) {
0262             $this->messages[] = 'Request failed.(' . $uri . ') OCS Matrix server send message: ' . $response->getBody();
0263 
0264             return false;
0265         }
0266 
0267         try {
0268             return Zend_Json::decode($response->getBody());
0269         } catch (Zend_Json_Exception $e) {
0270             Zend_Registry::get('logger')->err(__METHOD__ . ' - ' . $e->getMessage());
0271         }
0272 
0273         return false;
0274     }
0275 
0276     private function generateUserId($username)
0277     {
0278         $auth = $this->authAdmin();
0279 
0280         return "@{$username}:{$auth['home_server']}";
0281     }
0282 
0283     private function setAvatarUrl($userId, $contentUri)
0284     {
0285         $uri = $this->config->host . "/_matrix/client/r0/profile/{$userId}/avatar_url";
0286         $method = Zend_Http_Client::PUT;
0287         $data = array('avatar_url' => $contentUri);
0288 
0289         $result = $this->httpRequest($uri, '', $method, $data);
0290 
0291         return $result;
0292     }
0293 
0294     /**
0295      * @param string     $uri
0296      * @param string     $uid
0297      * @param string     $method
0298      * @param array|null $post_param
0299      *
0300      * @return bool|array
0301      * @throws Zend_Http_Client_Exception
0302      * @throws Zend_Json_Exception
0303      */
0304     protected function httpRequest($uri, $uid, $method = Zend_Http_Client::GET, $post_param = null)
0305     {
0306         $auth = $this->authAdmin();
0307 
0308         $this->httpServer->resetParameters();
0309         $this->httpServer->setUri($uri);
0310         $this->httpServer->setHeaders('Authorization', 'Bearer ' . $auth['access_token']);
0311         $this->httpServer->setHeaders('Content-Type', 'application/json');
0312         $this->httpServer->setHeaders('Accept', 'application/json');
0313         $this->httpServer->setHeaders('User-Agent', $this->config->user_agent);
0314         $this->httpServer->setMethod($method);
0315         if (isset($post_param)) {
0316             $jsonUserData = Zend_Json::encode($post_param);
0317             $this->httpServer->setRawData($jsonUserData, 'application/json');
0318         }
0319 
0320         $response = $this->httpServer->request();
0321         if ($response->getStatus() < 200 OR $response->getStatus() >= 400) {
0322             $this->messages[] = 'Request failed.(' . $uri . ') OCS Matrix server send message: ' . $response->getBody();
0323 
0324             return false;
0325         }
0326 
0327         $body = Zend_Json::decode($response->getBody());
0328 
0329         return $body;
0330     }
0331 
0332     /**
0333      * @param array $member_data
0334      * @param bool  $force
0335      *
0336      * @return bool|array
0337      * @throws Zend_Cache_Exception
0338      * @throws Zend_Exception
0339      * @throws Zend_Http_Client_Exception
0340      * @throws Zend_Json_Exception
0341      */
0342     public function createUserFromArray($member_data, $force = false)
0343     {
0344         if (empty($member_data)) {
0345             return false;
0346         }
0347 
0348         $this->messages = array();
0349 
0350         $usernameAvailable = $this->createUserAvailable($member_data['username']);
0351 
0352         if ($usernameAvailable) {
0353             try {
0354                 $method = Zend_Http_Client::POST;
0355                 $uri = $this->config->host . "/_matrix/client/r0/register?kind=user";
0356                 $session = $this->fetchSessionInfo($uri, Zend_Http_Client::POST, array('auth' => array()));
0357                 $data = array_merge($session, array('username' => $member_data['username'], 'password' => $member_data['password']));
0358                 $userLogin = $this->httpRequestWithoutToken($uri, $method, $data);
0359                 if (false === $userLogin) {
0360                     $this->messages[] = "Fail ";
0361 
0362                     return false;
0363                 }
0364                 $fileAvatar = $this->fetchAvatarFile($member_data['profile_image_url']);
0365                 $contentUri = $this->uploadAvatar($fileAvatar);
0366                 $result = $this->setAvatarUrl($userLogin['user_id'], $contentUri);
0367                 if (false === $result) {
0368                     $this->messages[] = "Fail ";
0369 
0370                     return false;
0371                 }
0372             } catch (Exception $e) {
0373                 $this->messages[] = "Fail : " . $e->getMessage();
0374 
0375                 return false;
0376             }
0377             $this->messages[] = "Create : Success";
0378 
0379             return $userLogin;
0380         }
0381 
0382         $this->messages[] = 'Fail : username already exists.';
0383 
0384         return false;
0385     }
0386 
0387     private function createUserAvailable($username)
0388     {
0389         try {
0390             $result = $this->httpRequest("{$this->config->host}/_matrix/client/r0/register/available?username={$username}", $username);
0391         } catch (Zend_Exception $e) {
0392             Zend_Registry::get('logger')->err(__METHOD__ . ' - ' . $e->getMessage());
0393         }
0394 
0395         return (isset($result['available']) && $result['available'] == true) ? true : false;
0396     }
0397 
0398     private function fetchSessionInfo($uri, $method = Zend_Http_Client::POST, $post_param = null)
0399     {
0400         $response = $this->httpRequestWithoutToken($uri, $method, $post_param);
0401 
0402         if ($response) {
0403             return array('auth' => array('type' => $response['flows'][0]['stages'][0], 'session' => $response['session']));
0404         }
0405 
0406         return array();
0407     }
0408 
0409     /**
0410      * @return mixed
0411      */
0412     public function getMessages()
0413     {
0414         return $this->messages;
0415     }
0416 
0417     private function requestAccess($uri, $uid, $method, $post_param)
0418     {
0419         $this->httpServer->resetParameters(true);
0420         $this->httpServer->setUri($uri);
0421         $this->httpServer->setHeaders('Content-Type', 'application/json');
0422         $this->httpServer->setHeaders('Accept', 'application/json');
0423         $this->httpServer->setHeaders('User-Agent', $this->config->user_agent);
0424         $this->httpServer->setMethod($method);
0425         if (isset($post_param)) {
0426             $jsonUserData = Zend_Json::encode($post_param);
0427             $this->httpServer->setRawData($jsonUserData, 'application/json');
0428         }
0429 
0430         $response = $this->httpServer->request();
0431         if ($response->getStatus() < 200 OR $response->getStatus() >= 400) {
0432             $this->messages[] = 'Request failed.(' . $uri . ') OCS Matrix server send message: ' . $response->getBody();
0433 
0434             return false;
0435         }
0436 
0437         $body = Zend_Json::decode($response->getBody());
0438 
0439         return $body;
0440     }
0441 
0442 }