function validate($data,&$cache,&$reason) { //make sure only valid properties are set $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->updateParams,true); if($validates && MediabirdConfig::$topicCountLimit !== false){ if(!property_exists($data, 'id')){ $select = "user_id = $this->userId AND mask = 1023"; $topicCount = $this->db->countRecords(MediabirdConfig::tableName('Right',true), $select); if($topicCount >= MediabirdConfig::$topicCountLimit){ $validates = false; $reason = MediabirdConstants::limitCountReached; } } } if($validates) { if(property_exists($data,'id')) { //data->id: integer, user must have access if(is_int($data->id)) { $select = "id=$data->id"; $record = $this->db->getRecord(MediabirdConfig::tableName('Topic',true),$select); if(!$record) { $validates = false; } //get access rights of current user $mask = $this->getTopicMask($data->id); if(!$mask) { $reason = MediabirdConstants::accessDenied; $validates = false; } // if topic id given: modification date must be supplied as well to make sure this topic hasn't changed in between! if($validates && (!property_exists($data,'modified') || !is_int($data->modified))) { $validates = false; } // make sure modification date matches database if($validates && $data->modified != $this->db->timestamp($record->modified)) { $reason = MediabirdConstants::invalidRevision; //fixme: client won't ask for update right now? $validates = false; } } else { $validates = false; } } else { //access rights default to user if topic is being created $mask = MediabirdTopicAccessConstants::owner; if(!property_exists($data,"title")) { $validates = false; } } if($validates && property_exists($data,"title") && !is_string($data->title) && strlen($data->title)>60) { $validates = false; } if($validates && property_exists($data,"title") && $mask < MediabirdTopicAccessConstants::allowRename) { $reason = MediabirdConstants::accessDenied; $validates = false; } } //data->newTags: array of object if($validates && property_exists($data,"newTags")) { //if tags are to be added, edit rights are required if($mask < MediabirdTopicAccessConstants::allowEditingContent) { $reason = MediabirdConstants::accessDenied; $validates = false; } if($validates && (!is_array($data->newTags) || count($data->newTags)==0)) { $validates = false; } if($validates) { $tagLabels = array(); foreach($data->newTags as $tag) { // maxlength: 30, minlength: 1 if(!is_string($tag) || strlen($tag) > 30 || strlen($tag)==0) { $validates = false; break; } else { $tagLabels[] = strtolower($tag); } } if($validates && !MediabirdUtility::checkUnique($tagLabels)) { $validates = false; } } } //data->cards: array of object, cards that are to be altered or added $cards = array(); if($validates && property_exists($data,'cards')) { if(!is_array($data->cards) || count($data->cards)==0 || !MediabirdUtility::checkUnique($data->cards,"id")) { $validates = false; } if($validates) { foreach($data->cards as $card) { if(!is_object($card) || !MediabirdUtility::checkKeyset($card,$this->cardProperties,true)) { $validates = false; break; } // * if card->id not given, card->type, card->title and card->index must be given if(!property_exists($card,'id') && (!property_exists($card,'type') || !property_exists($card,'title') || !property_exists($card,'index'))) { $validates = false; break; } //do not allow user to add, restructure or edit cards if not permitted if(!property_exists($card,'id')) { if($mask < MediabirdTopicAccessConstants::allowAddingCards) { $reason = MediabirdConstants::accessDenied; $validates = false; break; } } else { if(property_exists($card,'index') && $mask < MediabirdTopicAccessConstants::allowRearrangingCards) { $reason = MediabirdConstants::accessDenied; $validates = false; break; } //if card is to be altered, edit rights are required else if($mask < MediabirdTopicAccessConstants::allowEditingContent) { $reason = MediabirdConstants::accessDenied; $validates = false; } } //check tag indexes if given if(property_exists($card, 'tagIndexes')){ //new tags must be given if(!property_exists($data,'newTags')) { $validates = false; break; } //tag indexes must be given as array if(!is_array($card->tagIndexes)) { $validates = false; break; } //tag indexes must be in valid range and given as int foreach($card->tagIndexes as $tagIndex){ if(!is_int($tagIndex) || $tagIndex >= count($data->newTags) || $tagIndex < 0) { $validates = false; break; } } } //check if deleted tag ids are given if(property_exists($card, 'deletedTagIds')){ //deleted tag ids must be given as array if(!is_array($card->deletedTagIds)) { $validates = false; break; } //deleted tag ids must be given as int foreach($card->deletedTagIds as $deletedTagId){ if(!is_int($deletedTagId)){ $validates = false; break; } } } //if tags have been deleted or inserted, collect all existing tags if(property_exists($card, 'deletedTagIds') || property_exists($card, 'tagIndexes')){ //find tag that are already attached to this card $select = "card_id=".$card->id; //retrieve cardTag records and store them in cache $cardTagRecords = $this->db->getRecords(MediabirdConfig::tableName("CardTag",true),$select); $cache['cardTagRecords'][$card->id] = $cardTagRecords; //check if there are too many tag indexes if(property_exists($card, 'tagIndexes') && MediabirdConfig::$tagCountLimit !== false){ if((count($card->tagIndexes) + count($cardTagRecords)) >= MediabirdConfig::$tagCountLimit){ $validates = false; $reason = MediabirdConstants::limitCountReached; } } } // * if card->type given, it must be integer, valid and card->id must not be given if(property_exists($card,'type')) { if (!is_int($card->type) || !in_array($card->type,$this->allowedCardTypes) || property_exists($card,'id')) { $validates = false; break; } if($card->type == MediabirdConstants::cardTypeHtml || $card->type == MediabirdConstants::cardTypeWiki || $card->type == MediabirdConstants::cardTypeBlog) { if(property_exists($card,'uploadId') || property_exists($card,'page')) { $validates = false; break; } } else if($card->type == MediabirdConstants::cardTypePdf) { if(!property_exists($card,'uploadId') || !property_exists($card,'page') || !is_int($card->uploadId) || !is_int($card->page)) { $validates = false; break; } //check if upload is accessible and page refers to a valid number try { $mustOwn = true; //check if this upload has already been used in the topic if(property_exists($data,"id") && isset($data->id)) { $select = "content_type=".MediabirdConstants::cardTypePdf." AND content_id=$card->uploadId AND topic_id=$data->id"; if($this->db->countRecords(MediabirdConfig::tableName("Card",true),$select) > 0) { $mustOwn = false; } } //check if user is allowed to access the given pdf file if(!$this->controller->Files->checkFileAuth($card->uploadId,$mustOwn)) { $reason = MediabirdConstants::accessDenied; $validates = false; break; } } catch(Exception $ex) { $reason = MediabirdConstants::serverError; $validates = false; break; } } } // * if card->id given, either card->title or card->index must be given (otherwise nothing would change) if(property_exists($card,'id') && !property_exists($card,'title') && !property_exists($card,'index') && !property_exists($card,'tagIndexes') && !property_exists($card, 'deletedTagIds')) { $validates = false; break; } //* card->id: integer, optional if(property_exists($card,'id') && !is_int($card->id)) { $validates = false; break; } //* card->title: string, optional, maxlength 60 if(property_exists($card,'title') && !is_string($card->title) && strlen($card->title)>60) { $validates = false; break; } //* card->index: integer, optional if(property_exists($card,'index') && !is_int($card->index)) { $validates = false; break; } } } if($validates) { $cards = $data->cards; } } // //data->deletedCardIds: array of integer $deletedCardIds = array(); if($validates && property_exists($data,'deletedCardIds')) { if(!is_array($data->deletedCardIds) || count($data->deletedCardIds)==0 || !MediabirdUtility::checkUnique($data->deletedCardIds)) { $validates = false; } if($validates && $mask < MediabirdTopicAccessConstants::allowRemovingCards) { $reason = MediabirdConstants::accessDenied; $validates = false; } if($validates) { foreach($data->deletedCardIds as $deletedCardId) { if(!is_int($deletedCardId)) { $validates = false; break; } } } if($validates) { $deletedCardIds = $data->deletedCardIds; } } //* altogether, indexes must be a consecutive set of numbers if($validates && (count($deletedCardIds)>0 || count($cards)>0)) { //get existing cards $cardRecords = null; if(isset($record)) { $select = "topic_id=".$record->id; $currentRecords = $this->db->getRecords(MediabirdConfig::tableName('Card',true),$select,'','id,title,index_num,content_type,content_id'); $cardRecords = $currentRecords ? array_values($currentRecords) : null; } if(!$cardRecords) { $cardRecords = array(); } //check changes $checkedIds = array(); foreach($cards as $remoteCard) { if(property_exists($remoteCard,'id')) { //existing one is to be changed $found = false; foreach($cardRecords as $cardRecord) { if($cardRecord->id==$remoteCard->id) { // * ids must be unique if(in_array($remoteCard->id,$checkedIds)) { //id was given twice $validates = false; break; } $checkedIds []= $remoteCard->id; $found = true; if(property_exists($remoteCard,'index') && $cardRecord->index_num != $remoteCard->index) { $cardRecord->index_num = $remoteCard->index; } break; } } if(!$found) { //card was deleted meanwhile or update refers to a card not part of this topic $validates = false; } } else { $newRecord = (object)null; $newRecord->index_num = $remoteCard->index; $cardRecords[] = $newRecord; } } //validate cards that are to be deleted $deletedContentIds = array(); foreach($deletedCardIds as $deletedCardId) { $found = false; foreach($cardRecords as $key => $cardRecord) { if($cardRecord->id == $deletedCardId) { $found = true; break; } } if($found) { if( $cardRecord->content_type == MediabirdConstants::cardTypeHtml || $cardRecord->content_type == MediabirdConstants::cardTypeBlog || $cardRecord->content_type == MediabirdConstants::cardTypeWiki) { $deletedContentIds []= $cardRecord->content_id; } array_splice($cardRecords,$key,1); } else { //card id does not exist or does not belong to this topic! $validates = false; } } if($validates && count($deletedContentIds) > 0) { $minuteAgo = time()-60; $datetime = $this->db->datetime($minuteAgo); $select = "id IN (".join(",",$deletedContentIds).") AND locked_by NOT IN (0,$this->userId) AND locked_time>'$datetime'"; $lockedCount = $this->db->countRecords(MediabirdConfig::tableName("CardContent",true),$select); if($lockedCount > 0) { $validates = false; $reason = MediabirdConstants::locked; } } if($validates) { $indexes = array(); $cardIds = array(); //check if card indexes form a complete set foreach($cardRecords as $cardRecord) { $indexes[] = $cardRecord->index_num; if(property_exists($cardRecord,"id")) { $cardIds[] = intval($cardRecord->id); } } sort($indexes); foreach($indexes as $key=>$value) { if($validates && $key!=$value) { //there's a gap $validates = false; break; } } } // max card count if($validates && count($indexes)>MediabirdConstants::maxCardCount) { $validates = false; } if($validates) { $cache['cardRecords'] = isset($currentRecords) ? $currentRecords : array(); } } if($validates) { $cache['cards'] = $cards; $cache['deletedCardIds'] = $deletedCardIds; } if($validates) { $givenRightIds = array(); } //data->rights: array of object if($validates && property_exists($data,"rights")) { if(!is_array($data->rights) || count($data->rights)==0 || !MediabirdUtility::checkUnique($data->rights,"userId") || !MediabirdUtility::checkUnique($data->rights,"externalId") || !MediabirdUtility::checkUnique($data->rights,"email")) { $validates = false; } // if given: user must be owner of topic if($validates && isset($mask) && $mask != MediabirdTopicAccessConstants::owner) { $reason = MediabirdConstants::accessDenied; $validates = false; } $givenUserIds = array(); if($validates) { foreach($data->rights as $right) { if(!is_object($right) || !MediabirdUtility::checkKeyset($right,$this->rightProperties,true)) { $validates = false; break; } //if id given, must be integer if(property_exists($right,'id')) { //must be int and no other properties may be given if(!is_int($right->id) || property_exists($right,"userId") || property_exists($right,"externalId") || property_exists($right,"email")) { $validates = false; break; } $givenRightIds []= $right->id; } //* either one of right->id, right->userId, right->externalId, right->email must be given if(!property_exists($right,"id") && !property_exists($right,"userId") && !property_exists($right,"externalId") && !property_exists($right,"email")) { $validates = false; break; } //* right->userId: if given: must be integer, plus: must be among known users of if(property_exists($right,"userId")) { if(is_int($right->userId)) { if($right->userId == $this->userId) { $reason = MediabirdConstants::invalidData; $validates = false; break; } $givenUserIds []= $right->userId; } else { $validates = false; break; } } //* right->externalId: if given: must be integer, use external provider if(property_exists($right,"externalId") && !is_int($right->externalId)) { $validates = false; break; } //* right->email: if given: must be valid email address, search for user using that if(property_exists($right,"email") && !MediabirdUtility::checkEmail($right->email)) { $validates = false; break; } //* right->mask: integer, must be in valid access mask range (> none and <= owner) if(!property_exists($right,"mask") || !is_int($right->mask) || $right->mask <= MediabirdTopicAccessConstants::noAccess || $right->mask > MediabirdTopicAccessConstants::owner) { $validates = false; break; } } } if($validates && count($givenUserIds)>0) { $select = "id IN (".join(",",$givenUserIds).") AND id IN ( SELECT user_id FROM ".MediabirdConfig::tableName('Right')." WHERE mask>0 AND topic_id IN ( SELECT topic_id FROM ".MediabirdConfig::tableName('Right')." WHERE user_id=$this->userId AND mask>0 ) )"; if($this->db->countRecords(MediabirdConfig::tableName("User",true),$select) != count($givenUserIds)) { //user cannot know that user $validates = false; } } } //data->deletedRightIds: array of integer if($validates && property_exists($data,"deletedRightIds")) { // if given, topic must be given as well if(!isset($record)) { $validates = false; } if($validates && (!is_array($data->deletedRightIds) || count($data->deletedRightIds) == 0 || !MediabirdUtility::checkUnique($data->deletedRightIds))) { $validates = false; } // if more than one right will be removed: user must be owner of topic // if only one right is removed, it could be a leave request, will be checked later if($validates && count($data->deletedRightIds)>1 && $mask != MediabirdTopicAccessConstants::owner) { $reason = MediabirdConstants::accessDenied; $validates = false; } if($validates) { foreach($data->deletedRightIds as $deletedRightId) { if(is_int($deletedRightId)) { $givenRightIds []= $deletedRightId; } else { $validates = false; break; } } } if($validates && count($givenRightIds)==0) { $validates = false; } } //retrieve all existing right records if rights are inserted, updated or removed if($validates && (property_exists($data,"rights") || property_exists($data,"deletedRightIds"))) { $select ="topic_id=$record->id"; $rightRecords = $this->db->getRecords(MediabirdConfig::tableName("Right",true),$select); $rightRecords = $rightRecords ? $rightRecords : array(); //save for update function $cache['rightRecords'] = $rightRecords; } //check if ids of rights that are to be updated or deleted are valid if($validates && count($givenRightIds)>0) { //check if given right ids are unique if(!MediabirdUtility::checkUnique($givenRightIds)) { $validates = false; } //check if ids belong to this topic if($validates) { foreach($givenRightIds as $givenRightId) { $found = false; foreach($rightRecords as $rightRecord) { if ($rightRecord->id == $givenRightId) { $found = true; break; } } if(!$found) { //user cannot change that rightset $reason = MediabirdConstants::accessDenied; $validates = false; break; } else { if($rightRecord->user_id != $this->userId && $mask != MediabirdTopicAccessConstants::owner) { $reason = MediabirdConstants::accessDenied; $validates = false; break; } } } } } //check if at least one owner will be present if($validates && (property_exists($data,"rights") || property_exists($data,"deletedRightIds"))) { //check if at least one owner will remain after the changes would have been applied $ownerRemaining = false; if(!$ownerRemaining) { foreach($rightRecords as $rightRecord) { //check if this one is obsolete $rightId = intval($rightRecord->id); //if it will be overridden, ignore it if(in_array($rightId,$givenRightIds)) { continue; } //if it will be deleted, ignore it if(property_exists($data,"deletedRightIds") && in_array($rightId,$data->deletedRightIds)) { continue; } //if owner will remain, leave the loop if($rightRecord->mask == MediabirdTopicAccessConstants::owner) { $ownerRemaining = true; break; } } } //check new/altered rights if(!$ownerRemaining && property_exists($data,"rights")) { foreach($data->rights as $right) { if($right->mask == MediabirdTopicAccessConstants::owner) { $ownerRemaining = true; break; } } } if(!$ownerRemaining) { $validates = false; } } if($validates) { if(isset($record)) { $cache['record'] = $record; } $cache['mask'] = $mask; } if(!$validates && !isset($reason)) { $reason = MediabirdConstants::invalidData; } return $validates; }
/** * Validate session update * This does not alter User records */ function validate($data,&$cache,&$reason) { $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->stateProperties,true); $referredCardIds = array(); //checkOut must be given as integer if(property_exists($data,'checkOut') && !is_int($data->checkOut)) { $validates = false; } if($validates && property_exists($data,'cardId')) { //cardId must be integer if(is_int($data->cardId)) { $checkOut = property_exists($data,'checkOut') && $data->checkOut===1; $cardId = $data->cardId; $referredCardIds []= $cardId; } else { $validates = false; } } if($validates && property_exists($data,'checkOut') && !property_exists($data,'cardId')) { $validates = false; } if($validates && property_exists($data,'editing')) { //editing must be integer if(is_int($data->editing)) { $editingCard = $data->editing=='1'; } else { $validates = false; } } if($validates && property_exists($data,'checkInId')) { //id of card that is to be checked in must be integer if(is_int($data->checkInId)) { $checkInId = $data->checkInId; if(!in_array($checkInId,$referredCardIds)) { $referredCardIds []= $checkInId; } } else { $validates = false; } } //check if any cards are being referred (otherwise nothing to do!) if($validates && count($referredCardIds)==0) { $validates = false; } //check if user can access referred cards if($validates) { $minMask = ((isset($checkOut) && $checkOut) || isset($checkInId)) ? MediabirdTopicAccessConstants::allowEditingContent : MediabirdTopicAccessConstants::allowViewingCards; $select = "id IN (".join(",",$referredCardIds).") AND topic_id IN ( SELECT topic_id FROM ".MediabirdConfig::tableName('Right')." WHERE mask>=$minMask AND user_id=$this->userId )"; $cardRecords = $this->db->getRecords(MediabirdConfig::tableName("Card",true),$select); if(!$cardRecords || count($cardRecords) != count($referredCardIds)) { $reason = MediabirdConstants::invalidPage; $validates = false; } } if($validates) { $validTopicIds = array(); foreach($cardRecords as $cardRecord) { $validTopicIds []= intval($cardRecord->topic_id); } $cache['state']['validTopicIds'] = $validTopicIds; if(isset($cardId)) { $cache['state']['cardId'] = $cardId; $cache['state']['checkOut'] = $checkOut; } if(isset($checkInId)) { $cache['state']['checkInId'] = $checkInId; } } if(!$validates && !isset($reason)) { $reason = MediabirdConstants::invalidData; } return $validates; }
function validate($data,&$cache,&$reason) { $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->updateParams,true); /* case 1: a new check is to be created! * -> check is an object featuring an array of user ids check->userIds * * case 2: a state is to be changed * -> checkStatus is an object featuring state Id and new State */ //case 1 and 2 are exclusive, so disallow specifying checkStatus and check at the same time if($validates && property_exists($data,'check') && property_exists($data,'checkStatus')) { $validates = false; } //case 1: validate check if($validates && property_exists($data,'check')) { $check = $data->check; $validates = MediabirdUtility::checkKeyset($check,$this->checkProperties,false) && is_array($check->userIds) && MediabirdUtility::checkUnique($check->userIds); //check if all user ids are integer if($validates) { foreach($check->userIds as $userId) { if(!is_int($userId)) { $validates = false; break; } } } //check if at least one user id was given if($validates && sizeof($check->userIds)==0) { $validates = false; } //count matching records in DB if($validates) { //select users that are to be checked $select = "id IN (".join(",",$check->userIds).") AND "; //select users the current user knows $select .= "id IN (SELECT user_id FROM ".MediabirdConfig::tableName('Right')." WHERE mask>0 AND"; $count = 0; //select users from topics the current user has access to if($topics = $this->db->getRecords(MediabirdConfig::tableName('Right',true),"user_id=$this->userId AND mask>0",'','topic_id')) { $topicIds = array(); foreach($topics as $topic) { if(!in_array($topic->topic_id,$topicIds)) { $topicIds []= $topic->topic_id; } } $select .= " topic_id IN (".join(",",$topicIds)."))"; $count = $this->db->countRecords(MediabirdConfig::tableName('User',true),$select); } else { $validates = false; } if($validates && $count!=sizeof($check->userIds)) { $validates = false; } } } //case 2: validate checkStatus if($validates && property_exists($data,'checkStatus')) { $checkStatus = $data->checkStatus; $validates = MediabirdUtility::checkKeyset($checkStatus,$this->checkStatusProperties,false); //check if status is valid if($validates && !in_array($checkStatus->status,$this->validStatusCodes,true)) { $validates = false; } //check if state belongs to current user $select = "id=$checkStatus->id AND user_id=$this->userId"; if($validates && $this->db->countRecords(MediabirdConfig::tableName('CheckStatus',true),$select)!=1) { $validates = false; } } if(!$validates && !isset($reason)) { $reason = MediabirdConstants::invalidData; } return $validates; }
function validate($data,&$cache,&$reason) { $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->updateParams,true) && property_exists($data,'question') && is_object($data->question) && MediabirdUtility::checkKeyset($data->question,$this->questionProperties,true); //validate question if($validates) { $question = $data->question; //question id must be integer if(property_exists($question,'id') && !is_int($question->id)) { $validates = false; } //if question id is given, check that user is owner or has access if($validates && property_exists($question,'id')) { //check permission $select = "id=$question->id AND (user_id=$this->userId OR id IN ( SELECT relation_id FROM ".MediabirdConfig::tableName("Relation")." WHERE relation_type='question' AND marker_id IN ( SELECT id FROM ".MediabirdConfig::tableName("Marker")." WHERE shared=1 AND topic_id IN ( SELECT topic_id FROM ".MediabirdConfig::tableName("Right")." WHERE user_id=$this->userId AND mask>=".MediabirdTopicAccessConstants::allowViewingCards." ) ) ))"; if($questionRecord = $this->db->getRecord(MediabirdConfig::tableName("Question",true),$select)) { $cache['questionRecord']=$questionRecord; } else { $reason = MediabirdConstants::accessDenied; $validates = false; } } //at least id or {question,mode} must be given if($validates && !property_exists($question,'id') && (!property_exists($question,'question') || !property_exists($question,'mode'))){ $validates = false; } //check if question mode is valid if($validates && property_exists($question,'mode')) { if(!in_array($question->mode,$this->allowedQuestionModes,true)) { $validates = false; } } //check if question is string, no larger than max size if($validates && property_exists($question,'question')) { if($question->question !== null && (!is_string($question->question) || strlen($question->question)>$this->maxQuestionSize)) { $validates = false; } //if id given, user must be owner of question record if(property_exists($question,'id') && $questionRecord->user_id!=$this->userId) { $reason = MediabirdConstants::accessDenied; $validates = false; } } } //votes and stars may only be given if question already exists (so there is a chance that the answers exist as well) if($validates && !isset($questionRecord) && (property_exists($data,'votedAnswerIds')||property_exists($data,'unvotedAnswerIds')||property_exists($data,'starAnswerId'))) { $validates = false; } $referredAnswerIds = array(); //check vote answer ids if($validates && property_exists($data,'votedAnswerIds')) { if(!is_array($data->votedAnswerIds) || count($data->votedAnswerIds)==0 || !MediabirdUtility::checkUnique($data->votedAnswerIds)) { $validates = false; } if($validates) { foreach($data->votedAnswerIds as $votedAnswerId) { if(!is_int($votedAnswerId)) { $validates = false; break; } $referredAnswerIds []= $votedAnswerId; } } } //check unvote answer ids if($validates && property_exists($data,'unvotedAnswerIds')) { if(!is_array($data->unvotedAnswerIds) || count($data->unvotedAnswerIds)==0 || !MediabirdUtility::checkUnique($data->unvotedAnswerIds)) { $validates = false; } if($validates) { foreach($data->unvotedAnswerIds as $unvotedAnswerId) { if(!is_int($unvotedAnswerId)) { $validates = false; break; } //unvoted answers must currently be voted for $unvotedAnswerIds []= $unvotedAnswerId; //unvoted answers must not be in the list of voted answers if(in_array($unvotedAnswerId,$referredAnswerIds)) { $validates = false; break; } } } //check if unvoted answers are currently voted for if($validates) { $select = "answer_id IN (".join(",",$unvotedAnswerIds).") AND user_id=$this->userId"; if($this->db->countRecords(MediabirdConfig::tableName("Vote",true),$select)!=count($unvotedAnswerIds)) { $reason = MediabirdConstants::accessDenied; $validates = false; } } } //check star answer id if($validates && property_exists($data,'starAnswerId')) { if(!is_int($data->starAnswerId)) { $validates = false; } else { if($data->starAnswerId !=0 && array_search($data->starAnswerId,$referredAnswerIds)===false) { $referredAnswerIds []= $data->starAnswerId; } } } //save changed answer ids $updatedAnswerIds = array(); //validate answers if($validates && property_exists($data,'answers')) { if(!is_array($data->answers) || count($data->answers)==0 || !MediabirdUtility::checkUnique($data->answers,'id')) { $validates = false; } if($validates) { foreach($data->answers as $answer) { if(!is_object($answer) || !MediabirdUtility::checkKeyset($answer,$this->answerProperties,true)) { $validates = false; break; } //answer id must be integer if(property_exists($answer,'id') && !is_int($answer->id)) { $validates = false; break; } //if answer id given, question must exist and an answer be given if(property_exists($answer,'id') && (!property_exists($answer,'answer') || !isset($questionRecord))) { $validates = false; break; } //either id or answer must be given if(!property_exists($answer,'id') && !property_exists($answer,'answer')){ $validates = false; break; } //check if question is string, no larger than max size and if id given, user must be owner of question record if(property_exists($answer,'answer')) { if(!is_string($answer->answer) || strlen($answer->answer)>$this->maxAnswerSize) { $validates = false; break; } } //if question id is given, check that user is owner if(property_exists($answer,'id')) { $updatedAnswerIds []= $answer->id; } } if($validates && count($updatedAnswerIds)>0) { //only owner may edit question $select = "id IN (".join(",",$updatedAnswerIds).") AND user_id=$this->userId AND question_id=$questionRecord->id"; $answerRecords = $this->db->getRecords(MediabirdConfig::tableName("Answer",true),$select); if($answerRecords && count($answerRecords) == count($updatedAnswerIds)) { $cache['answerRecords'] = $answerRecords; } else { $reason = MediabirdConstants::accessDenied; $validates = false; } } } } //remove checked answers from list of answers that are to be checked if($validates && count($referredAnswerIds)>0 && count($updatedAnswerIds)>0) { foreach($updatedAnswerIds as $answerId) { $key = array_search($answerId,$referredAnswerIds); if($key!==false) { array_splice($referredAnswerIds,$key,1); } } } //validate deleted answers array if($validates && property_exists($data,'deletedAnswerIds')) { //answers may not be deleted if there is no question record if(!isset($questionRecord)) { $validates = false; } if($validates && !is_array($data->deletedAnswerIds) || count($data->deletedAnswerIds)==0 || !MediabirdUtility::checkUnique($data->deletedAnswerIds)) { $validates = false; } //all ids must be int if($validates) { foreach($data->deletedAnswerIds as $deletedAnswerId) { if(!is_int($deletedAnswerId)) { $validates = false; break; } //if answer that is to be deleted is being referred to by votes, starring or updated answers, validation fails if($validates && (array_search($deletedAnswerId,$referredAnswerIds)!==false || array_search($deletedAnswerId,$updatedAnswerIds)!==false)) { $validates = false; break; } } } } //include unvoted answers in check if($validates && isset($unvotedAnswerIds)) { $referredAnswerIds = array_merge($referredAnswerIds,$unvotedAnswerIds); } //check if voted, unvoted or starred answers are accessible if($validates && count($referredAnswerIds)>0) { //only answer must be related to given question (since that is owned by or shared with current user) $select = "id IN (".join(",",$referredAnswerIds).") AND question_id=$questionRecord->id"; if($this->db->countRecords(MediabirdConfig::tableName("Answer",true),$select) != count($referredAnswerIds)) { $reason = MediabirdConstants::accessDenied; $validates = false; } } //check if to be deleted answers really can be deleted if($validates && property_exists($data,'deletedAnswerIds')) { //only owners may delete answers, answer must belong to this question //question_id <=> parent field $select = "id IN (".join(",",$data->deletedAnswerIds).") AND user_id=$this->userId AND question_id=$questionRecord->id"; if($this->db->countRecords(MediabirdConfig::tableName("Answer",true),$select)!=count($data->deletedAnswerIds)) { $reason = MediabirdConstants::accessDenied; $validates = false; } } if(!$validates && !isset($reason)) { $reason = MediabirdConstants::invalidData; } return $validates; }
function validate($data,&$cache,&$reason) { /* incoming: * links * link.url (string, maxlength $maxUrlLength) * link.title (string, maxlength $maxTitleLength) * link.type (any of $allowedTypes) * link.id (integer) * deletedLinkIds * * generally: only owner can change or delete links */ $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->updateParams,true); $referredIds = array(); if($validates && property_exists($data,'links')) { //check if links is an array, if it contains has at least one member, if the referred ids do not occur twice if(!is_array($data->links) || count($data->links) == 0 || !MediabirdUtility::checkUnique($data->links,'id')) { $validates = false; } if($validates) { foreach ($data->links as $link) { if(!MediabirdUtility::checkKeyset($link,$this->linkProperties,true)) { $validates = false; break; } //if no id given, all url, title and type must be given if(!property_exists($link,'id') && (!property_exists($link,'url') || !property_exists($link,'type') || !property_exists($link,'title'))) { $validates = false; break; } //if id given, it must be integer if(property_exists($link,'id')) { if(!is_int($link->id)) { $validates = false; break; } $referredIds []= $link->id; } //type must be in $allowedTypes if given if(property_exists($link,'type') && !in_array($link->type,$this->allowedTypes,true)) { $validates = false; break; } //title must be smaller than max size if given if(property_exists($link,'title') && (!is_string($link->title) || strlen($link->title) > $this->maxTitleLength)) { $validates = false; break; } //url must be smaller than max size if given if(property_exists($link,'url') && (!is_string($link->url) || strlen($link->url) > $this->maxUrlLength)) { $validates = false; break; } if(property_exists($link,'url')) { //fixme: validate url scheme here } } } } if($validates && property_exists($data,'deletedLinkIds')) { if(!is_array($data->deletedLinkIds) || count($data->deletedLinkIds)==0 || !MediabirdUtility::checkUnique($data->deletedLinkIds)) { $validates = false; } if($validates) { foreach($data->deletedLinkIds as $deletedLinkId) { if(!is_int($deletedLinkId)) { $validates = false; break; } $referredIds []= $deletedLinkId; } } } if($validates && count($referredIds)>0) { //check if user has access to these ids $select = "id IN (".join(",",$referredIds).") AND user_id=$this->userId"; if(!$records = $this->db->getRecords(MediabirdConfig::tableName("Link",true),$select,'','id,user_id')) { $validates = false; } if($validates && count($records) != count($referredIds)) { $validates = false; } } if($validates) { $cache['linkRecords'] = isset($records) ? $records : array(); } if(!$validates && !isset($reason)) { $reason = MediabirdConstants::invalidData; } return $validates; }
function feedback($args) { if(!MediabirdUtility::checkKeyset($args,array('desc'))) { return false; } $description = $args->desc; $results = array(); $body = "User with id $this->userId has suggested the following feature:\n".$description; $body = wordwrap($body, 70); if (!MediabirdConfig::$disable_mail) { $oldReporting = error_reporting(0); if (method_exists($this->auth, 'sendMail') && $this->auth->sendMail(-1, "Mediabird Feedback", $body)) { $result = MediabirdConstants::processed; } else { $result = MediabirdConstants::serverError; } error_reporting($oldReporting); } else { error_log("Feature suggested by user $this->userId: $description ."); $result = MediabirdConstants::processed; } $results['r'] = $result; return $results; }
function validateCopy($data,&$cache,&$reason) { //incoming: array of ids to be deep-copied $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->copyParams); if($validates && (!is_array($data->ids) || count($data->ids)==0)) { $validates = false; } if($validates) { foreach($data->ids as $id) { if(!is_int($id)) { $validates = false; break; } } } if($validates) { //select files that the current user was granted access to (protected files) $select .= "id IN ( SELECT upload_id FROM ".MediabirdConfig::tableName("UploadAccess")." WHERE user_id=$this->userId AND mask>0 )"; //select files of users the current user knows $select .= " OR id IN ( SELECT content_id FROM ".MediabirdConfig::tableName("Card")." WHERE content_type=".MediabirdConstants::cardTypePdf." AND topic_id IN ( SELECT topic_id FROM ".MediabirdConfig::tableName('Right')." WHERE user_id=$this->userId AND mask>0 ) )"; //select files not owned by current user (slicing) $select = "user_id != $this->userId AND (".$select.")"; //slice by given ids $select = "id IN (".join(",",$data->ids).") AND (".$select.")"; $records = $this->db->getRecords(MediabirdConfig::tableName("Upload",true),$select); if(!$records || count($records) != count($data->ids)) { $validates = false; } } if($validates) { $cache['uploadRecords'] = isset($records) ? $records : array(); } if(!$validates && !isset($reason)) { $reason = MediabirdConstants::invalidData; } return $validates; }
function validate($data,&$cache,&$reason) { $time = time(); /* incoming: * flashcards * flashcard.results (array, items must be member of $allowedResults) * flashcard.answerTime (int, must be smaller than $time) * flashcard.level (any of $allowedLevels) * flashcard.id (integer) * deletedFlashcardIds * * generally: only owner can change or delete flashcards */ $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->updateParams,true); $referredIds = array(); if($validates && property_exists($data,'flashcards')) { //check if flashcards is an array, if it contains has at least one member, if the referred ids do not occur twice if(!is_array($data->flashcards) || count($data->flashcards) == 0 || !MediabirdUtility::checkUnique($data->flashcards,'id')) { $validates = false; } if($validates) { foreach ($data->flashcards as $flashcard) { if(!MediabirdUtility::checkKeyset($flashcard,$this->flashcardProperties,true)) { $validates = false; break; } //if no id given, all results, answerTime and level must be given if(!property_exists($flashcard,'id') && (!property_exists($flashcard,'results') || !property_exists($flashcard,'answerTime') || !property_exists($flashcard,'level'))) { $validates = false; break; } //if id given, it must be integer if(property_exists($flashcard,'id')) { if(!is_int($flashcard->id)) { $validates = false; break; } $referredIds []= $flashcard->id; } //type must be in $allowedLevels if given if(property_exists($flashcard,'level') && !in_array($flashcard->level,$this->allowedLevels,true)) { $validates = false; break; } //answer time must be equal or smaller than current time if(property_exists($flashcard,'answerTime') && (!is_int($flashcard->answerTime) || $flashcard->answerTime > $time)) { $validates = false; break; } //results must be an array of integers in the range $allowedResults if(property_exists($flashcard,'results')) { if( !is_array($flashcard->results) || count($flashcard->results)!=$this->resultsCount) { $validates = false; break; } foreach($flashcard->results as $result) { if(!in_array($result,$this->allowedResults,true)) { $validates = false; break; } } if(!$validates) { break; } } } } } if($validates && property_exists($data,'deletedFlashcardIds')) { if(!is_array($data->deletedFlashcardIds) || count($data->deletedFlashcardIds)==0 || !MediabirdUtility::checkUnique($data->deletedFlashcardIds)) { $validates = false; } if($validates) { foreach($data->deletedFlashcardIds as $deletedFlashcardId) { if(!is_int($deletedFlashcardId)) { $validates = false; break; } $referredIds []= $deletedFlashcardId; } } } if($validates && count($referredIds)>0) { //check if user has access to these ids $select = "id IN (".join(",",$referredIds).") AND user_id=$this->userId"; if(!$records = $this->db->getRecords(MediabirdConfig::tableName("Flashcard",true),$select,'','id')) { $validates = false; } if($validates && count($records) != count($referredIds)) { $validates = false; } } if($validates) { $cache['flashcardRecords'] = isset($records) ? $records : array(); } if(!$validates && !isset($reason)) { $reason = MediabirdConstants::invalidData; } return $validates; }
function validate($data,&$cache,&$reason) { $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->updateParams) && is_array($data->tagColors) && count($data->tagColors)>0; $referredTagIds = array(); if($validates) { foreach($data->tagColors as $tagColor) { //check if only valid keys are given if(!MediabirdUtility::checkKeyset($tagColor,$this->tagProperties,true)) { $validates = false; break; } //check if id and at least color or showText are given if(!property_exists($tagColor,'tagId') || (!property_exists($tagColor,'color') && !property_exists($tagColor,'showText'))) { $validates = false; break; } //tag id must be given as int if(!is_int($tagColor->tagId)) { $validates = false; break; } if(!in_array($tagColor->tagId,$referredTagIds,true)) { $referredTagIds []= $tagColor->tagId; } else { //tagId should not be given twice $validates = false; break; } //validate color if(property_exists($tagColor,'color') && !$this->validateHexColor($tagColor->color)) { $validates = false; break; } //validate showText if(property_exists($tagColor,'showText') && !in_array($tagColor->showText,$this->allowedShowStates,true)) { $validates = false; break; } } if($validates) { $select = "id IN (".join(",",$referredTagIds).")"; if($this->db->countRecords(MediabirdConfig::tableName("Tag",true),$select)!=count($referredTagIds)) { $validates = false; } else { $cache ['referredTagIds'] = $referredTagIds; } } } if(!$validates && !isset($reason)) { $reason = MediabirdConstants::invalidData; } return $validates; }
/** * Determines marker ids and card ids of markers related to a given set of object ids */ function findMarkers($data,$relationType,&$results) { $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->findMarkerParams,true) && is_array($data->ids); if($validates) { foreach($data->ids as $id) { if(!is_int($id)) { $validates = false; break; } } } if($validates) { //enough validation! $select = "id IN ( SELECT marker_id FROM ".MediabirdConfig::tableName("Relation")." WHERE relation_type='".$relationType."' AND relation_id IN (".join(",",$data->ids).") ) AND ( user_id=$this->userId OR (shared=1 AND topic_id IN ( SELECT topic_id FROM ".MediabirdConfig::tableName("Right")." WHERE user_id=$this->userId AND mask>=".MediabirdTopicAccessConstants::allowViewingCards." )) )"; //array to store infos about the markers $markerInfos = array(); //now get all related markers $markerRecords = $this->db->getRecords(MediabirdConfig::tableName("Marker",true),$select,'','id,card_id'); if($markerRecords) { foreach($markerRecords as $markerRecord) { $markerInfo = (object)array( 'id'=>intval($markerRecord->id), 'cardId'=>intval($markerRecord->card_id) ); $markerInfos []= $markerInfo; } } if(isset($results['markerInfos'])) { $results['markerInfos'] = array_merge($results['markerInfos'],$markerInfos); } else { $results['markerInfos'] = $markerInfos; } return true; } else { $results['r'] = MediabirdConstants::invalidData; return false; } }
function validate($data,&$cache,&$reason) { $validates = is_object($data) && MediabirdUtility::checkKeyset($data,$this->updateParams,true); //id must be integer if($validates && (!property_exists($data,"id") || !is_int($data->id))) { $validates = false; } if($validates && property_exists($data,"content") && ((!is_string($data->content) && $data->content != null) || strlen($data->content) > MediabirdContent::maxCardSize)) { //if given, content must be string and smaller in size than maxsize $validates = false; } //card must exist and user must have access rights if($validates) { $select = "card_id=$data->id AND topic_id IN ( SELECT topic_id FROM ".MediabirdConfig::tableName('Right')." WHERE mask>=".MediabirdTopicAccessConstants::allowEditingContent." AND user_id=$this->userId )"; if(!$record = $this->db->getRecord(MediabirdConfig::tableName('CardContent',true),$select)) { $reason = MediabirdConstants::accessDenied; $validates = false; } } //if content given, modification date must be supplied as well to make sure this card hasn't changed in between! if($validates && property_exists($data,"content") && (!property_exists($data,'modified') || !is_int($data->modified))) { $validates = false; } // make sure modification date matches database value if content given if($validates && property_exists($data,"content") && $data->modified != $this->db->timestamp($record->modified)) { $reason = MediabirdConstants::invalidRevision; $validates = false; } if($validates) { //check check-out condition $minuteAgo = time()-60; $locked = $record->locked_by != $this->userId && $record->locked_by != 0 && $this->db->timestamp($record->locked_time) > $minuteAgo; if($locked) { $reason = MediabirdConstants::locked; $validates = false; } } if($validates && property_exists($data,'checkout')) { $validates = in_array($data->checkout,array(0,1),true); } if($validates && property_exists($data,'content')) { $cache['content'] = $data->content != null ? MediabirdUtility::purifyHTML($data->content) : null; } if($validates) { $cache['record'] = $record; } if(!$validates && !isset($reason)) { $reason = MediabirdConstants::invalidData; } return $validates; }