xenforoaddon_mobileAppApi/upload/library/mobileAppApi/ControllerPublic/MobileApi.php

1049 lines
35 KiB
PHP

<?php
class mobileAppApi_ControllerPublic_MobileApi extends XenForo_ControllerPublic_Abstract {
public $fc;
public static $apiVersion = 1;
public function getApiMods(){
return [];
}
protected function _preDispatch($action){
//setting framework
$this->_routeMatch->setResponseType('json');
//making usable by mobile apps
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: X-Requested-With,content-type');
//json headers
header('Content-Type: application/json; charset=utf-8');
//decoding json input and incorporating to the request
$phpInput = file_get_contents("php://input");
if($phpInput){ //workaround to be able to send brackets in message
try{
//static::returnJson([false, $phpInput]);
$decoded='';
for($i=0;$i<strlen($phpInput);$i+=4){
$bucket = substr($phpInput,$i,4);
$char = json_decode('"\u'.$bucket.'"');
$decoded.= $char;
}
//static::returnJson([false, $decoded]);
$arrayPosted = json_decode($decoded,true);
//static::returnJson([false, $arrayPosted]);
if(getType($arrayPosted)==='array'){
foreach($arrayPosted as $id=>$val){
try{
$this->_request->setParam(strval($id),strval($val));
}catch(Exception $e){;}catch(Error $e){;}catch(ErrorException $e){;}
}
}
//static::returnJson([false,$this->_input->filterSingle('cookie', XenForo_Input::STRING)]);
}catch(Exception $e){;}catch(Error $e){;}catch(ErrorException $e){;}
}
//static::returnJson([false, $arrayPosted]);
//setting user up
$visitor = XenForo_Visitor::getInstance();
$sessionObj = XenForo_Application::getSession();
//* Saving previous session
$previousSessionId = $sessionObj->getSessionId();
$previousUserId = $visitor->user_id;
//* Reading new session
$data = $this->_input->filterSingle('cookie', XenForo_Input::STRING);
if($data){
$userId=0;
$sessionId="";
$cookieKey="";
try{
list($userId,$sessionId,$cookieKey) = json_decode($data);
}catch(Exception $e){;}
$userId = intval($userId);
if($userId && $sessionId && $cookieKey){
//* Checking received session
$expiredSession = false;
//** First: get the session
$newSession = $sessionObj->getSessionFromSource($sessionId);
if($newSession===false){
$expiredSession = true;
$newSession = [];
}
//** Then get the user from the session
$newUserId = array_key_exists('user_id',$newSession)?$newSession['user_id']:0;
//** Check if the cookie key belongs to the wanted user
$keyMatches = ($cookieKey === $this->_getUserModel()->getUserRememberKeyForCookie($userId, null));
//** Check if the wanted user is the user of the session
$wantedUserMatches = ($userId === $newUserId);
//** Veredictum to check if session will be changed
$authorized = $keyMatches && $wantedUserMatches;
if($authorized){
$sessionSetup = new ReflectionMethod($sessionObj,'_setup');
$sessionSetup->setAccessible(true);
$sessionSetup->invoke($sessionObj,$sessionId);
$newSessionId = $sessionObj->getSessionId();
if($newSessionId===$sessionId){ //IP check passed and session set
XenForo_Visitor::setup($userId);
}else{ //IP check failed
$sessionObj->delete(); //save space from database
$sessionSetup->invoke($sessionObj,$previousSessionId);
$this->impersonationDetected();
}
}else if($expiredSession){
; //it happens
}else{
$this->impersonationDetected();
}
}
}
//XenForo_Visitor::setup(785);
$visitor = XenForo_Visitor::getInstance();
$unsetupVisitor = false;
if(array_key_exists('user_deactivated_kiroraddon',$visitor->toArray())){
if($visitor->toArray()['user_deactivated_kiroraddon']){
$unsetupVisitor = true;
}
}
if($visitor->toArray()['is_banned']){
$unsetupVisitor = true;
}
if($unsetupVisitor){
XenForo_Visitor::setup(0);
}
$visitor = XenForo_Visitor::getInstance();
//getting front controller
$this->fc = $this->_getClassInstanceFromBacktrace('XenForo_FrontController');
//because no one develops good solutions without understanding the output
//static::$prettyfiedJson = true;
$this->_routeMatch->setResponseType('html');
//running parent preDispatch actions
return parent::_preDispatch($action);
}
public function impersonationDetected(){;}
public static $prettyfiedJson = false;
public static function returnJson($data = null){
if(static::$prettyfiedJson){
$data = json_encode($data,JSON_PRETTY_PRINT);
}else{
$data = json_encode($data);
}
die($data);
}
public static function debug($data = null){
die(print_r($data,true));
}
public function actionError(){
static::returnJson();
}
public function actionIndex(){
$listed = get_class_methods($this);
$methods = [];
foreach($listed as $method){
if(strpos($method,'action')===0){
$methods[]=substr($method,6);
}
}
$r = [
'api_version'=>static::$apiVersion,
'api_mods'=>$this->getApiMods(),
'android_apk'=>null,
'methods'=>$methods,
];
$r['android_apk'] = XenForo_Application::getOptions()->boardUrl.'/app.apk';
$r['boardUrl'] = XenForo_Application::getOptions()->boardUrl.'';
static::returnJson($r);
}
public function actionTermsOfService(){
$data = (new XenForo_Phrase('terms_rules_text'))->__toString();
static::returnJson($data);
}
public function _getClassInstanceFromBacktrace($class){
foreach(debug_backtrace() as $backtrace){
if(
array_key_exists('object',$backtrace)
&&
$backtrace['class']===$class
){
return $backtrace['object'];
}
}
static::returnJson("Couldn't find class ".$class." in backtrace.");
}
public function _getProtectedAttribute($obj, $prop) {
$reflection = new ReflectionClass($obj);
$property = $reflection->getProperty($prop);
$property->setAccessible(true);
return $property->getValue($obj);
}
public function _getBaseView(){
return new XenForo_ViewPublic_Base(
new XenForo_ViewRenderer_HtmlPublic(
$this->_getProtectedAttribute($this->fc, '_dependencies'),
$this->_getProtectedAttribute($this->fc, '_response'),
$this->_getProtectedAttribute($this->fc, '_request')
),
$this->_getProtectedAttribute($this->fc, '_response'),
[],
'PAGE_CONTAINER'
);
}
public function _getUserModel(){
return $this->getModelFromCache('XenForo_Model_User');
}
public function _getLoginModel(){
return $this->getModelFromCache('XenForo_Model_Login');
}
public function _getAlertModel(){
return $this->getModelFromCache('XenForo_Model_Alert');
}
public function _getThreadModel(){
return $this->getModelFromCache('XenForo_Model_Thread');
}
public function _getThreadPrefixModel(){
return $this->getModelFromCache('XenForo_Model_ThreadPrefix');
}
public function _getForumModel(){
return $this->getModelFromCache('XenForo_Model_Forum');
}
public function _getPostModel(){
return $this->getModelFromCache('XenForo_Model_Post');
}
public function _getSpamPreventionModel(){
return $this->getModelFromCache('XenForo_Model_SpamPrevention');
}
public function _getThreadWatchModel(){
return $this->getModelFromCache('XenForo_Model_ThreadWatch');
}
public function _getNodeModel(){
return $this->getModelFromCache('XenForo_Model_Node');
}
public function _getChatModel(){
return $this->getModelFromCache('Siropu_Chat_Model');
}
public function _getChatHelper(){
return $this->getHelper('Siropu_Chat_Helper');
}
public function actionLogin($asMethod = false){
$data = $this->_input->filter([
'lgn' => XenForo_Input::STRING,
'pwd' => XenForo_Input::STRING
]);
if($data['lgn']===''){
static::returnJson([false,"Fields incomplete","Login is empty"]);
}
if($data['pwd']===''){
static::returnJson([false,"Fields incomplete","Password is empty"]);
}
$userModel = $this->_getUserModel();
$loginModel = $this->_getLoginModel();
if($loginModel->requireLoginCaptcha($data['lgn'])){
static::returnJson([false,"Too many failed attempts","Wait some minutes"]);
}
$userId = $userModel->validateAuthentication($data['lgn'], $data['pwd'], $error);
if(!$userId){
$loginModel->logLoginAttempt($data['lgn']);
static::returnJson([false,"Wrong credentials",strval($error)]);
}
$loginModel->clearLoginAttempts($data['lgn']);
$user = $this->_getUserModel()->getFullUserById($userId);
$loginHelper = $this->getHelper('Login');
$visitor = XenForo_Visitor::setup($userId);
if(array_key_exists('user_deactivated_kiroraddon',$visitor->toArray())){
if($visitor->toArray()['user_deactivated_kiroraddon']){
static::returnJson([false,"Unauthorized","This account is deactivated"]);
}
}
if($visitor->toArray()['is_banned']){
static::returnJson([false,"Unauthorized","This member is banned"]);
}
$visitor = XenForo_Visitor::setup(0);
if($asMethod){
return $user;
}
if($loginHelper->userTfaConfirmationRequired($user)){
$tfaModel = $this->getModelFromCache('XenForo_Model_Tfa');
$providers = $tfaModel->getTfaConfigurationForUser($user['user_id'], $userData);
if($providers){
static::returnJson(['2fa','Two-factor authentication']);
}
}
$this->finishLogin($userId);
}
public function finishLogin($userId){
$userModel = $this->_getUserModel();
$cookieKey = $userModel->getUserRememberKeyForCookie($userId, null);
XenForo_Model_Ip::log($userId, 'user', $userId, 'login');
$userModel->deleteSessionActivity(0, $this->_request->getClientIp(false));
$visitor = XenForo_Visitor::setup($userId);
XenForo_Application::getSession()->userLogin($userId, $visitor['password_date']);
$sessionObj = XenForo_Application::getSession();
$session_id = $sessionObj->getSessionId();
$sessionObj->save();
static::returnJson([true,json_encode([$userId,$session_id,$cookieKey])]);
}
public function actionLoginTfa(){
$user = $this->actionLogin(true);
$loginHelper = $this->getHelper('Login');
$tfaModel = $this->getModelFromCache('XenForo_Model_Tfa');
$providers = $tfaModel->getTfaConfigurationForUser($user['user_id'], $userData);
if(!$providers){$this->finishLogin($user['user_id']);}
$providerId = $this->_input->filterSingle('provider', XenForo_Input::STRING);
if($providerId){
$validationResult = $loginHelper->runTfaValidation($user, $providerId, $providers, $userData);
if($validationResult===true){
$this->finishLogin($user['user_id']);
}
static::returnJson([false,'Authentication has failed']);
}
$vp = [];
foreach($providers as $id=>$pv){
$vp[]=[
'type'=>$id,
'title'=>strval($pv->getTitle()),
'desc'=>strval($pv->getDescription()),
];
$loginHelper->triggerTfaCheck($user, $id, $providers, $userData);
}
static::returnJson([
false,
strval(
new XenForo_Phrase('email_has_been_sent_to_x_with_code',['email'=>$user['email']])
),
$vp
]);
}
public function actionLogout(){
$this->getModelFromCache('XenForo_Model_Session')->processLastActivityUpdateForLogOut(XenForo_Visitor::getUserId());
XenForo_Application::getSession()->delete();
XenForo_Helper_Cookie::deleteAllCookies(
array('session'),
array('user' => array('httpOnly' => false))
);
static::returnJson(true);
}
public function actionAlertList(){
$visitor = XenForo_Visitor::getInstance();
$alertModel = $this->_getAlertModel();
$alerts = $alertModel->getAlertsForUser(
$visitor->user_id,
$alertModel::PREVENT_MARK_READ
);
return $this->responseView('mobileAppApi_ViewPublic_MobileApi','',[
'mode'=>'alertCompiler',
'alerts'=>$alerts
]);
}
public function actionAlertMarkRead(){
$visitor = XenForo_Visitor::getInstance();
$alertModel = $this->_getAlertModel();
$alertModel->markAllAlertsReadForUser($visitor->user_id);
return $this->actionAlertList();
}
public function actionMyData(){
$visitor = XenForo_Visitor::getInstance();
static::returnJson($visitor->toArray());
}
public function actionMyDataMini(){
$visitor = XenForo_Visitor::getInstance();
$mini = [
'user_id' => $visitor->user_id,
'username' => $visitor->username,
'custom_title' => $visitor->custom_title,
'alerts_unread' => $visitor->alerts_unread,
'conversations_unread' => $visitor->conversations_unread,
];
static::returnJson($mini);
}
public function actionListForum(){
$visitor = XenForo_Visitor::getInstance();
$fm = $this->_getForumModel();
$fn = [];
$fn2 = XenForo_Model::create('XenForo_Model_Node')->getAllNodes();
$nodedatalist = XenForo_Model::create('XenForo_Model_Node')->getNodeDataForListDisplay(false,0);
$fnref = array_keys($nodedatalist['nodeParents']);
foreach($fnref as $nid){
if(array_key_exists($nid,$fn2)){
$fn[$nid] = $fn2[$nid];
}
}
$forums = [];
foreach($fn as $f){
if($f['node_type_id']=='Forum' || $f['node_type_id']=='Category'){
if(!$f['display_in_list']){
continue;
}
$np = $visitor->getNodePermissions($f['node_id']);
if(array_key_exists('view',$np) && $np['view']===true){
if(!$f['display_in_list']){
continue;
}
$forum = [
'id'=>$f['node_id'],
'nm'=>$f['title'],
'dc'=>$f['description'],
'dp'=>$f['depth'],
'fr'=>$f['node_type_id']=='Forum',
'ct'=>$f['node_type_id']=='Category',
'nw'=>false,
];
if($forum['fr']){ //if is forum
$ed = $this->_getForumModel()->getExtraForumDataForNodes(
[$f['node_id']],
['readUserId'=>$visitor->user_id]
);
$ed = $f+$ed[$f['node_id']];
$ed = $this->_getForumModel()->prepareForum($ed);
$forum['nw'] = $ed['hasNew'];
}
$forums[]=$forum;
}
}
}
for($i=0; $i<count($forums)-1; $i++){
if($forums[$i]['ct'] && $forums[$i]['dp']>$forums[$i+1]['dp']){
unset($forums[$i]);
$forums = array_merge($forums);
$i--;
}
}
$forums = array_merge($forums);
if($forums[count($forums)-1]['ct']){
unset($forums[count($forums)-1]);
}
static::returnJson($forums);
}
//public function actionListForum(){return $this->responseView('mobileAppApi_ViewPublic_MobileApi','',['mode'=>'forumNodeCompiler','nodeList'=>$this->_getNodeModel()->getNodeDataForListDisplay(false, 0)]);}
public function actionForumListThread(){
$visitor = XenForo_Visitor::getInstance();
$forumId = $this->_input->filterSingle('frm', XenForo_Input::UINT);
$threadModel = $this->_getThreadModel();
$forumModel = $this->_getForumModel();
$forum = [];
try{
$forum = $this->getHelper('ForumThreadPost')->assertForumValidAndViewable(
$forumId,
[
'readUserId' => $visitor->user_id,
'watchUserId' => $visitor->user_id
]
);
} catch(Exception $e){
static::returnJson([]);
}
$page = max(1,$this->_input->filterSingle('pag', XenForo_Input::UINT));
$threadsPerPage = 100;
$order = $forum['default_sort_order'];
$orderDirection = $forum['default_sort_direction'];
$displayConditions = [];
$prefixId = $this->_input->filterSingle('prfx', XenForo_Input::UINT);
if ($prefixId){
$displayConditions['prefix_id'] = $prefixId;
}
$threadFetchConditions = $displayConditions + $threadModel->getPermissionBasedThreadFetchConditions($forum);
$threadFetchConditions['deleted']=false;
$threadFetchConditions['moderated']=false;
$threadFetchOptions = array(
'join' => XenForo_Model_Thread::FETCH_USER,
'readUserId' => $visitor['user_id'],
'watchUserId' => $visitor['user_id'],
'postCountUserId' => $visitor['user_id'],
'perPage' => $threadsPerPage,
'page' => $page,
'order' => $order,
'orderDirection' => $orderDirection
);
$totalThreads = $threadModel->countThreadsInForum($forumId, $threadFetchConditions);
$threads = $threadModel->getThreadsInForum($forumId, $threadFetchConditions, $threadFetchOptions);
$threadPrefixModel = $this->_getThreadPrefixModel();
foreach($threads as &$thread){
$prefixId = $thread['prefix_id'];
$prefixPhrase = $threadPrefixModel->getPrefixTitlePhraseName($prefixId);
$prefix = strval(new XenForo_Phrase($prefixPhrase));
$thread['prefix_has'] = $prefix!=$prefixPhrase;
$thread['prefix'] = $prefix==$prefixPhrase?'':$prefix;
unset($thread);
}
$threads2 = [];
$lessinfo = [
'thread_id',
'prefix_id',
'prefix_has',
'prefix',
'title',
'reply_count',
'user_id',
'username',
'last_post_id',
'last_post_user_id',
'last_post_username',
'last_post_date',
'thread_read_date',
];
foreach($threads as $thread){
$abridged = [];
foreach($lessinfo as $info){
$abridged[$info] = $thread[$info];
}
$abridged['has_unread'] = $abridged['last_post_date'] > $abridged['thread_read_date'];
unset($abridged['last_post_date']);
unset($abridged['thread_read_date']);
$threads2[$thread['thread_id']] = $abridged;
}
static::returnJson([
'page'=>$page,
'pages'=>ceil($totalThreads/$threadsPerPage),
'threads'=>$threads2,
]);
}
public function actionForumThreadListPost(){
$visitor = XenForo_Visitor::getInstance();
$threadId = $this->_input->filterSingle('thd', XenForo_Input::UINT);
$threadFetchOptions = array(
'readUserId' => $visitor['user_id'],
'watchUserId' => $visitor['user_id'],
'draftUserId' => $visitor['user_id'],
'join' => XenForo_Model_Thread::FETCH_AVATAR
);
$forumFetchOptions = array(
'readUserId' => $visitor['user_id']
);
$ftpHelper = $this->getHelper('ForumThreadPost');
list($thread, $forum) = $ftpHelper->assertThreadValidAndViewable($threadId, $threadFetchOptions, $forumFetchOptions);
$threadModel = $this->_getThreadModel();
$postModel = $this->_getPostModel();
if($threadModel->isRedirect($thread)){
static::returnJson(null);
}
$page = 1;
$postsPerPage = 10000;
$postFetchOptions = $this->_getPostModel()->getPermissionBasedPostFetchOptions($thread, $forum) + array(
'join' => XenForo_Model_Post::FETCH_USER
| XenForo_Model_Post::FETCH_USER_PROFILE
| XenForo_Model_Post::FETCH_BBCODE_CACHE,
'likeUserId' => XenForo_Visitor::getUserId()
);
$postFetchOptions += array(
'perPage' => $postsPerPage,
'page' => $page
);
$posts = $postModel->getPostsInThread($threadId, $postFetchOptions);
$posts = $postModel->getAndMergeAttachmentsIntoPosts($posts);
$maxPostDate = 0;
$pagePosition = 0;
$firstUnreadPostId = 0;
$permissions = $visitor->getNodePermissions($thread['node_id']);
foreach ($posts AS $id=>&$post){
$post['position_on_page'] = ++$pagePosition;
$post = $postModel->preparePost($post, $thread, $forum, $permissions);
if ($post['post_date'] > $maxPostDate){
$maxPostDate = $post['post_date'];
}
if ($post['isDeleted']){
unset($posts[$id]);
continue;
}
if ($post['isModerated']){
unset($posts[$id]);
continue;
}
if (!$firstUnreadPostId && $post['isNew']){
$firstUnreadPostId = $post['post_id'];
}
unset($post);
}
$threadModel->markThreadRead($thread, $forum, $maxPostDate);
$threadModel->logThreadView($threadId);
return $this->responseView('mobileAppApi_ViewPublic_MobileApi', '', [
'mode'=>'postCompiler',
'posts'=>$posts,
'firstUnreadPost'=>$firstUnreadPostId,
'thread'=>$thread,
'forum'=>$forum
]);
}
public function actionListRecentThreadPosts(){
$visitor = XenForo_Visitor::getInstance();
$autoReadDate = XenForo_Application::$time - (XenForo_Application::getOptions()->readMarkingDataLifetime * 86400);
$threadModel = $this->_getThreadModel();
$threads = $threadModel->getThreads(
[
'deleted' => false,
'moderated' => false,
'find_new' => true,
'not_discussion_type' => 'redirect',
'last_post_date' => array('>', $autoReadDate)
],[
'limit' => 250,
'join' =>
XenForo_Model_Thread::FETCH_FORUM |
XenForo_Model_Thread::FETCH_FORUM_OPTIONS |
XenForo_Model_Thread::FETCH_LAST_POST_AVATAR,
'permissionCombinationId' => $visitor->permission_combination_id,
'readUserId' => $visitor->user_id,
'order' => 'last_post_date',
'forceThreadIndex' => 'last_post_date'
]
);
$threadPrefixModel = $this->_getThreadPrefixModel();
foreach($threads as &$thread){
$np = $visitor->getNodePermissions($thread['node_id']);
if(!(array_key_exists('view',$np) && $np['view']===true)){
unset($threads[$thread['thread_id']]);
}else{
$prefixId = $thread['prefix_id'];
$prefixPhrase = $threadPrefixModel->getPrefixTitlePhraseName($prefixId);
$prefix = strval(new XenForo_Phrase($prefixPhrase));
$thread['prefix_has'] = $prefix!=$prefixPhrase;
$thread['prefix'] = $prefix==$prefixPhrase?'':$prefix;
}
unset($thread);
}
$threads2 = [];
$lessinfo = [
'node_id',
'thread_id',
'prefix_id',
'prefix_has',
'prefix',
'title',
'node_title',
'reply_count',
'username',
'user_id',
'last_post_id',
'last_post_user_id',
'last_post_username',
'last_post_date',
'thread_read_date',
];
foreach($threads as $thread){
if($threadModel->isRedirect($thread)){
continue;
}
$abridged = [];
foreach($lessinfo as $info){
$abridged[$info] = $thread[$info];
}
$abridged['isNew'] = (
array_key_exists('thread_read_date',$abridged)
&&
array_key_exists('last_post_date',$abridged)
&&
$abridged['last_post_date'] > $abridged['thread_read_date']
);
$threads2[$thread['thread_id']] = $abridged;
}
static::returnJson($threads2);
}
public function actionForumInsertThread(){
$visitor = XenForo_Visitor::getInstance();
$testingPermissions = $this->_input->filterSingle('permtst', XenForo_Input::UINT);
$forumId = $this->_input->filterSingle('frm', XenForo_Input::UINT);
$ftpHelper = $this->getHelper('ForumThreadPost');
try{
$forum = $ftpHelper->assertForumValidAndViewable($forumId);
}catch(Exception $e){
static::returnJson([false,"Error","Forum is not valid or viewable"]);
}
$forumId = $forum['node_id'];
if(!$this->_getForumModel()->canPostThreadInForum($forum, $errorPhraseKey)){
try{
static::returnJson([false,"Can't post into forum",strval(new XenForo_Phrase($errorPhraseKey))]);
}catch(ErrorException $e){
static::returnJson([false,"Can't reply into thread",""]);
}
}
if($testingPermissions){
static::returnJson([true,"Allowed","Can reply into thread"]);
}
$input = $this->_input->filter(array(
'title' => XenForo_Input::STRING,
'prefix_id' => XenForo_Input::UINT,
'attachment_hash' => XenForo_Input::STRING,
'tags' => XenForo_Input::STRING,
'watch_thread_state' => XenForo_Input::UINT,
'watch_thread' => XenForo_Input::UINT,
'watch_thread_email' => XenForo_Input::UINT,
'_set' => array(XenForo_Input::UINT, 'array' => true),
'discussion_open' => XenForo_Input::UINT,
'sticky' => XenForo_Input::UINT,
'poll' => XenForo_Input::ARRAY_SIMPLE,
));
$input['attachment_hash'] = '';
$input['tags'] = '';
$input['watch_thread_state'] = 1;
$input['watch_thread'] = 1;
$input['watch_thread_email'] = 1;
$input['_set'] = [];
$input['discussion_open'] = 1;
$input['sticky'] = 0;
$input['poll'] = [];
$input['message'] = $this->getHelper('Editor')->getMessageText('message', $this->_input);
$input['message'] = XenForo_Helper_String::autoLinkBbCode($input['message']);
$writer = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread');
$writer->bulkSet(array(
'user_id' => $visitor['user_id'],
'username' => $visitor['username'],
'title' => $input['title'],
'prefix_id' => $input['prefix_id'],
'node_id' => $forumId
));
$writer->set('discussion_state', $this->getModelFromCache('XenForo_Model_Post')->getPostInsertMessageState(array(), $forum));
$postWriter = $writer->getFirstMessageDw();
$postWriter->set('message', $input['message']);
$postWriter->setExtraData(XenForo_DataWriter_DiscussionMessage::DATA_ATTACHMENT_HASH, $input['attachment_hash']);
$postWriter->setExtraData(XenForo_DataWriter_DiscussionMessage_Post::DATA_FORUM, $forum);
$postWriter->setOption(XenForo_DataWriter_DiscussionMessage_Post::OPTION_MAX_TAGGED_USERS, $visitor->hasPermission('general', 'maxTaggedUsers'));
$writer->setExtraData(XenForo_DataWriter_Discussion_Thread::DATA_FORUM, $forum);
$pollWriter = false;
$tagger = null;
$spamModel = $this->_getSpamPreventionModel();
$spamMessage = '';
if (!$writer->hasErrors()
&& $writer->get('discussion_state') == 'visible'
&& $spamModel->visitorRequiresSpamCheck()
)
{
switch ($spamModel->checkMessageSpam($input['title'] . "\n" . $input['message'], array(), $this->_request)){
case XenForo_Model_SpamPrevention::RESULT_MODERATED:
//$writer->set('discussion_state', 'moderated');
//let it pass
break;
case XenForo_Model_SpamPrevention::RESULT_DENIED;
$spamModel->logSpamTrigger('thread', null);
$spamMessage = new XenForo_Phrase('your_content_cannot_be_submitted_try_later');
$writer->error($spamMessage);
break;
}
}
$writer->preSave();
if ($forum['require_prefix'] &&
!$writer->get('prefix_id') &&
$this->_getPrefixModel()->getUsablePrefixesInForums($forum['node_id']))
{
$writer->set('prefix_id',$forum['default_prefix_id']);
}
if (!$writer->hasErrors()){
$this->assertNotFlooding('post');
}
$writer->save();
$thread = $writer->getMergedData();
$spamModel->logContentSpamCheck('thread', $thread['thread_id']);
$spamModel->logSpamTrigger('thread', $thread['thread_id']);
$this->_getThreadWatchModel()->setVisitorThreadWatchStateFromInput($thread['thread_id'], $input);
$this->_getThreadModel()->markThreadRead($thread, $forum, XenForo_Application::$time);
static::returnJson([true,"Success",strval(new XenForo_Phrase('your_thread_has_been_posted'))]);
}
public function actionForumThreadInsertPost(){
$visitor = XenForo_Visitor::getInstance();
$testingPermissions = $this->_input->filterSingle('permtst', XenForo_Input::UINT);
$threadId = $this->_input->filterSingle('thd', XenForo_Input::UINT);
$ftpHelper = $this->getHelper('ForumThreadPost');
$threadFetchOptions = array('readUserId' => $visitor['user_id']);
$forumFetchOptions = array('readUserId' => $visitor['user_id']);
try{
list($thread, $forum) = $ftpHelper->assertThreadValidAndViewable($threadId, $threadFetchOptions, $forumFetchOptions);
}catch(Exception $e){
static::returnJson([false,"Error","Thread is not valid or viewable"]);
}
if (!$this->_getThreadModel()->canReplyToThread($thread, $forum, $errorPhraseKey)){
try{
static::returnJson([false,"Can't reply into thread",strval(new XenForo_Phrase($errorPhraseKey))]);
}catch(ErrorException $e){
static::returnJson([false,"Can't reply into thread",""]);
}
}
if($testingPermissions){
static::returnJson([true,"Allowed","Can reply into thread"]);
}
$input = $this->_input->filter(array(
'attachment_hash' => XenForo_Input::STRING,
'watch_thread_state' => XenForo_Input::UINT,
'watch_thread' => XenForo_Input::UINT,
'watch_thread_email' => XenForo_Input::UINT,
'_set' => array(XenForo_Input::UINT, 'array' => true),
'discussion_open' => XenForo_Input::UINT,
'sticky' => XenForo_Input::UINT,
));
$input['attachment_hash'] = '';
$input['watch_thread_state'] = 1;
$input['watch_thread'] = 1;
$input['watch_thread_email'] = 1;
$input['_set'] = [];
$input['discussion_open'] = 1;
$input['sticky'] = 0;
$input['message'] = $this->getHelper('Editor')->getMessageText('message', $this->_input);
$input['message'] = XenForo_Helper_String::autoLinkBbCode($input['message']);
$writer = XenForo_DataWriter::create('XenForo_DataWriter_DiscussionMessage_Post');
$writer->set('user_id', $visitor['user_id']);
$writer->set('username', $visitor['username']);
$writer->set('message', $input['message']);
$writer->set('message_state', $this->_getPostModel()->getPostInsertMessageState($thread, $forum));
$writer->set('thread_id', $threadId);
$writer->setExtraData(XenForo_DataWriter_DiscussionMessage::DATA_ATTACHMENT_HASH, $input['attachment_hash']);
$writer->setExtraData(XenForo_DataWriter_DiscussionMessage_Post::DATA_FORUM, $forum);
$writer->setOption(XenForo_DataWriter_DiscussionMessage_Post::OPTION_MAX_TAGGED_USERS, $visitor->hasPermission('general', 'maxTaggedUsers'));
$spamModel = $this->_getSpamPreventionModel();
$spamMessage = '';
if (!$writer->hasErrors()
&& $writer->get('message_state') == 'visible'
&& $spamModel->visitorRequiresSpamCheck()
)
{
$spamExtraParams = array(
'permalink' => XenForo_Link::buildPublicLink('canonical:threads', $thread)
);
switch ($spamModel->checkMessageSpam($input['message'], $spamExtraParams, $this->_request))
{
case XenForo_Model_SpamPrevention::RESULT_MODERATED:
//$writer->set('message_state', 'moderated');
//let it pass
break;
case XenForo_Model_SpamPrevention::RESULT_DENIED;
$spamModel->logSpamTrigger('post', null);
$spamMessage = new XenForo_Phrase('your_content_cannot_be_submitted_try_later');
$writer->error($spamMessage);
break;
}
}
$writer->preSave();
if (!$writer->hasErrors()){
$this->assertNotFlooding('post');
}
$writer->save();
$post = $writer->getMergedData();
$spamModel->logContentSpamCheck('post', $post['post_id']);
$spamModel->logSpamTrigger('post', $post['post_id']);
$this->_getThreadWatchModel()->setVisitorThreadWatchStateFromInput($threadId, $input);
static::returnJson([true,"Success",strval(new XenForo_Phrase('your_message_has_been_posted'))]);
}
public function actionChatPermissions($asMethod = false){
$visitor = XenForo_Visitor::getInstance();
$chatEnabled = XenForo_Application::getOptions()->siropu_chat_page['enabled'];
$chatPermissions = $visitor->permissions['siropu_chat'];
$chatPermissions['chatBanned'] = boolval($this->_getChatModel()->getBanByUserAndRoomId($visitor->user_id, -1, 'ban'));
$chatPermissions['chatKicked'] = $this->_getChatModel()->getBanByUserAndRoomId($visitor->user_id, -1, 'kick');
$chatPermissions['chatKicked']|= $this->_getChatModel()->getBanByUserAndRoomId($visitor->user_id, 0, 'kick');
$chatPermissions['chatKicked'] = boolval($chatPermissions['chatKicked']);
$chatPermissions['chatMuted'] = $this->_getChatModel()->getBanByUserAndRoomId($visitor->user_id, -1, 'mute');
$chatPermissions['chatMuted']|= $this->_getChatModel()->getBanByUserAndRoomId($visitor->user_id, 0, 'mute');
$chatPermissions['chatMuted'] = boolval($chatPermissions['chatMuted']);
$permissions = [];
$permissions['see'] = $chatEnabled && $chatPermissions['view'] && (!($chatPermissions['chatBanned'] || $chatPermissions['chatKicked']));
$permissions['say'] = $chatEnabled && $permissions['see'] && $chatPermissions['use'] && !$chatPermissions['chatMuted'];
if($asMethod){
return $permissions;
}
static::returnJson($permissions);
}
public function actionChatListRooms($asMethod = false){
$visitor = XenForo_Visitor::getInstance();
if(!$this->actionChatPermissions(true)['see']){
$this->actionError();
}
$rooms = $this->_getChatModel()->getAllRooms();
foreach($rooms as $id=>&$room){
$room['room_name'] = strval($room['room_name']);
$room['room_description'] = strval($room['room_description']);
if(!array_key_exists('hasPermission',$room)){
$room['hasPermission'] = $this->_getChatHelper()->checkRoomPermissions($room);
}
if(
!$room['hasPermission']
||
(array_key_exists('room_password',$room)&&boolval($room['room_password']))
||
(array_key_exists('room_locked',$room)&&boolval($room['room_locked']))
||
boolval($this->_getChatModel()->getBanByUserAndRoomId($visitor->user_id,$room['room_id'],'ban'))
||
boolval($this->_getChatModel()->getBanByUserAndRoomId($visitor->user_id,$room['room_id'],'kick'))
){
unset($rooms[$id]);
}
$room['muted']=boolval($this->_getChatModel()->getBanByUserAndRoomId($visitor->user_id,$room['room_id'],'mute'));
unset($room);
unset($id);
}
ksort($rooms);
$rooms2 = [];
foreach($rooms as $id=>$room){
$rooms2[$id]=[
'room_id' => $room['room_id'],
'room_name' => $room['room_name'],
'room_description' => $room['room_description'],
'room_speakable' => !$room['muted']
];
}
if($asMethod){
return $rooms2;
}
static::returnJson([array_keys($rooms2),array_values($rooms2)]);
}
public function actionChatRoomListMessages(){
$visitor = XenForo_Visitor::getInstance();
if(!$this->actionChatPermissions(true)['see']){
$this->actionError();
}
$rooms = array_keys($this->actionChatListRooms(true));
$lastMessage = $this->_input->filterSingle('messagelatest', XenForo_Input::UINT);
$pollingTime = $this->_input->filterSingle('pollingtime', XenForo_Input::UINT);
if($pollingTime<5){ //Won't overload the server with short pollings
$pollingTime = 5;
}else if($pollingTime>25){ //XenForo limits this the request time to 30
$pollingTime = 25;
}
$msgs = [];
for($i = 0; $i<($pollingTime*4); $i++){
$gotData = false;
foreach($rooms as $room){
$ms = $this->_getChatModel()->getMessages([
'order'=>'date_desc',
'room_id'=>$room,
'last_id'=>$lastMessage,
]);
$msgs[$room] = $ms;
if(count($ms)>0){
$gotData = true;
}
}
if($gotData){
return $this->responseView('mobileAppApi_ViewPublic_MobileApi','',[
'mode'=>'chatMessageCompiler',
'data'=>$msgs
]);
}else{
usleep(1000*250);//250 ms
}
}
static::returnJson([]);
}
public function actionChatRoomOnlineGet(){
$visitor = XenForo_Visitor::getInstance();
if(!$this->actionChatPermissions(true)['see']){
$this->actionError();
}
$roomid = $this->_input->filterSingle('roomid', XenForo_Input::UINT);
$active = $this->_getChatModel()->getActiveUsers();
if(array_key_exists($roomid,$active)){
static::returnJson($active[$roomid]['data']);
}
static::returnJson([]);
}
public function actionChatRoomMessageSend(){
$visitor = XenForo_Visitor::getInstance();
if(!$this->actionChatPermissions(true)['say']){
static::returnJson([false,"Insufficient permissions"]);
}
$roomid = $this->_input->filterSingle('roomid', XenForo_Input::UINT);
$message = $this->_input->filterSingle('message', XenForo_Input::STRING);
$rooms = $this->actionChatListRooms(true);
if(array_key_exists($roomid,$rooms)){
if($rooms[$roomid]['room_speakable']){
if(!$message){
static::returnJson([false,"Cannot send empty messages"]);
}
$chatSession = $this->_getChatModel()->getSession($visitor->user_id);
if(!$chatSession){
$dw = XenForo_DataWriter::create('Siropu_Chat_DataWriter_Sessions');
$dw->setExistingData($this->userId);
$dw->set('user_is_banned', 0);
$dw->set('user_is_muted', 0);
$dw->save();
unset($dw);
}
$chatSession = $this->_getChatModel()->getSession($visitor->user_id);
$csr = unserialize($chatSession['user_rooms']);
if(getType($csr)!='array'){
$csr = [];
}
$csr[$roomid]=time();
$chatSession['user_rooms']=serialize($csr);
$chatSession['user_last_activity']=time();
$chatSession['user_message_count']+=1;
$sw = XenForo_DataWriter::create('Siropu_Chat_DataWriter_Sessions');
$sw->setExistingData($visitor->user_id);
$sw->bulkSet($chatSession);
$sw->save();
//static::returnJson($chatSession);
$pfx = XenForo_Application::getOptions()->chatMobilePrefix;
$dw = XenForo_DataWriter::create('Siropu_Chat_DataWriter_Messages');
$dw->set('message_room_id',$roomid);
$dw->set('message_user_id',$visitor->user_id);
$dw->set('message_text',$pfx?$pfx.' '.$message:$message);
$dw->save();
if($dw->hasErrors()){
static::returnJson([false,"DataWriter failed"]);
}
static::returnJson([true,"Success"]);
}
static::returnJson([false,"Insufficient permissions"]);
}
static::returnJson([false,"Room doesn't exist"]);
}
}