Esempio n. 1
0
	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;
	}
Esempio n. 2
0
	/**
	 * 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;
	}
Esempio n. 3
0
	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;
	}
Esempio n. 4
0
	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;	 
	}
Esempio n. 5
0
	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;
	}
Esempio n. 6
0
	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;
	}
Esempio n. 7
0
	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;
	}
Esempio n. 8
0
	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;
	}
Esempio n. 9
0
	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;
	}
Esempio n. 10
0
	/**
	 * 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;
		}
	}
Esempio n. 11
0
	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;
	}