get_channel(); if(($aid) && (x($_REQUEST,'channel'))) { // Only change channel if it is different than the current channel if($channel && x($channel,'channel_address') && $channel['channel_address'] != $_REQUEST['channel']) { $c = q("select channel_id from channel where channel_address = '%s' and channel_account_id = %d limit 1", dbesc($_REQUEST['channel']), intval($aid) ); if((! $c) || (! change_channel($c[0]['channel_id']))) return false; } } if ($_SESSION["allow_api"]) return local_channel(); return false; } function api_date($str){ //Wed May 23 06:01:13 +0000 2007 return datetime_convert('UTC', 'UTC', $str, "D M d H:i:s +0000 Y" ); } function api_register_func($path, $func, $auth=false){ global $API; $API[$path] = array('func'=>$func, 'auth'=>$auth); } /************************** * MAIN API ENTRY POINT * **************************/ function api_call(&$a){ GLOBAL $API, $called_api; // preset $type="json"; foreach ($API as $p=>$info){ if (strpos($a->query_string, $p)===0){ $called_api= explode("/",$p); //unset($_SERVER['PHP_AUTH_USER']); if ($info['auth'] === true && api_user() === false) { api_login($a); } load_contact_links(api_user()); $channel = $a->get_channel(); logger('API call for ' . $channel['channel_name'] . ': ' . $a->query_string); logger('API parameters: ' . print_r($_REQUEST,true)); $type="json"; if (strpos($a->query_string, ".xml")>0) $type="xml"; if (strpos($a->query_string, ".json")>0) $type="json"; if (strpos($a->query_string, ".rss")>0) $type="rss"; if (strpos($a->query_string, ".atom")>0) $type="atom"; if (strpos($a->query_string, ".as")>0) $type="as"; $r = call_user_func($info['func'], $a, $type); if ($r===false) return; switch($type){ case "xml": $r = mb_convert_encoding($r, "UTF-8",mb_detect_encoding($r)); header ("Content-Type: text/xml"); return ''."\n".$r; break; case "json": header ("Content-Type: application/json"); foreach($r as $rr) { if(! $rr) $rr = array(); $json = json_encode($rr); } if ($_GET['callback']) $json = $_GET['callback']."(".$json.")"; return $json; break; case "rss": header ("Content-Type: application/rss+xml"); return ''."\n".$r; break; case "atom": header ("Content-Type: application/atom+xml"); return ''."\n".$r; break; case "as": //header ("Content-Type: application/json"); //foreach($r as $rr) // return json_encode($rr); return json_encode($r); break; } //echo "
"; var_dump($r); die();
			}
		}
		header("HTTP/1.1 404 Not Found");
		logger('API call not implemented: '.$a->query_string." - ".print_r($_REQUEST,true));
		$r = 'not implemented 0.9.7 ' . "\r\n";
			killme();
		}
		elseif($type === 'json') {
			header("Content-type: application/json");
			echo '"0.9.7"';
			killme();
		}
	}
	api_register_func('api/statusnet/version','api_statusnet_version',false);
	function api_friendica_version(&$a,$type) {
		if($type === 'xml') {
			header("Content-type: application/xml");
			echo '' . "\r\n" . '' . Zotlabs\Project\System::get_project_version() . ' ' . "\r\n";
			killme();
		}
		elseif($type === 'json') {
			header("Content-type: application/json");
			echo '"' . Zotlabs\Project\System::get_project_version() . '"';
			killme();
		}
	}
	api_register_func('api/friendica/version','api_friendica_version',false);
	api_register_func('api/red/version','api_friendica_version',false);
	function api_ff_ids(&$a,$type,$qtype) {
		if(! api_user())
			return false;
		// For Red, the closest thing we can do to figure out if you're friends is if both of you are sending each other your streams.
		// This won't work if either of you send your stream to everybody on the network
		if($qtype == 'friends')
			$sql_extra = sprintf(" AND ( abook_their_perms & %d )>0 and ( abook_my_perms & %d )>0 ", intval(PERMS_W_STREAM), intval(PERMS_W_STREAM));
		if($qtype == 'followers')
			$sql_extra = sprintf(" AND ( abook_my_perms & %d )>0 and not ( abook_their_perms & %d )>0 ", intval(PERMS_W_STREAM), intval(PERMS_W_STREAM));
 
		$r = q("SELECT abook_id FROM abook where abook_self = 0 and abook_channel = %d $sql_extra",
			intval(api_user())
		);
		if(is_array($r)) {
			if($type === 'xml') {
				header("Content-type: application/xml");
				echo '' . "\r\n" . '' . "\r\n";
				foreach($r as $rr)
					echo '' . $rr['abook_id'] . ' ' . "\r\n";
				echo ' ' . "\r\n";
				killme();
			}
			elseif($type === 'json') {
				$ret = array();
				header("Content-type: application/json");
				foreach($r as $rr) $ret[] = $rr['abook_id'];
				echo json_encode($ret);
				killme();
			}
		}
	}
	function api_friends_ids(&$a,$type) {
		api_ff_ids($a,$type,'friends');
	}
	function api_followers_ids(&$a,$type) {
		api_ff_ids($a,$type,'followers');
	}
	api_register_func('api/friends/ids','api_friends_ids',true);
	api_register_func('api/followers/ids','api_followers_ids',true);
	function api_direct_messages_new(&$a, $type) {
		if (api_user()===false) return false;
		
		if (!x($_POST, "text") || !x($_POST,"screen_name")) return;
		$sender = api_get_user($a);
		
		require_once("include/message.php");
		// in a decentralised world the screen name is ambiguous
		$r = q("SELECT `abook_id` FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE `abook_channel`=%d and xchan_addr like '%s'",
				intval(api_user()),
				dbesc($_POST['screen_name'] . '@%')
		);
		$recipient = api_get_user($a, $r[0]['abook_id']);			
		$replyto = '';
		$sub     = '';
		if (x($_REQUEST,'replyto')) {
			$r = q('SELECT `parent_mid`, `title` FROM `mail` WHERE `uid`=%d AND `id`=%d',
					intval(api_user()),
					intval($_REQUEST['replyto']));
			$replyto = $r[0]['parent_mid'];
			$sub     = $r[0]['title'];
		}
		else {
			if (x($_REQUEST,'title')) {
				$sub = $_REQUEST['title'];
			}
			else {
				$sub = ((strlen($_POST['text'])>10)?substr($_POST['text'],0,10)."...":$_POST['text']);
			}
		}
		$id = send_message(api_user(),$recipient['guid'], $_POST['text'], $sub, $replyto);
		if ($id>-1) {
			$r = q("SELECT * FROM `mail` WHERE id=%d", intval($id));
			$ret = api_format_message($r[0], $recipient, $sender);
		
		} else {
			$ret = array("error"=>$id);	
		}
		
		$data = Array('$messages'=>$ret);
		
		switch($type){
			case "atom":
			case "rss":
				$data = api_rss_extra($a, $data, $user_info);
		}
				
		return  api_apply_template("direct_messages", $type, $data);
				
	}
	api_register_func('api/direct_messages/new','api_direct_messages_new',true);
	function api_direct_messages_box(&$a, $type, $box) {
		if (api_user()===false) return false;
		
		$user_info = api_get_user($a);
		
		// params
		$count = (x($_GET,'count')?$_GET['count']:20);
		$page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0);
		if ($page<0) $page=0;
		
		$start = $page*$count;
		$channel = $a->get_channel();		
		$profile_url = $a->get_baseurl() . '/channel/' . $channel['channel_address'];
		if ($box=="sentbox") {
			$sql_extra = "`from_xchan`='".dbesc( $channel['channel_hash'] )."'";
		}
		elseif ($box=="conversation") {
			$sql_extra = "`parent_mid`='".dbesc( $_GET["uri"] )  ."'";
		}
		elseif ($box=="all") {
			$sql_extra = "true";
		}
		elseif ($box=="inbox") {
			$sql_extra = "`from_xchan`!='".dbesc( $channel['channel_hash'] )."'";
		}
		
		$r = q("SELECT * FROM `mail` WHERE channel_id = %d AND $sql_extra ORDER BY created DESC LIMIT %d OFFSET %d",
				intval(api_user()),
				intval($count), intval($start)
		);
		
		$ret = Array();
		if($r) {
			foreach($r as $item) {
				if ($item['from_xchan'] == $channel['channel_hash']) {
					$sender = $user_info;
					$recipient = api_get_user($a, null, $item['to_xchan']);
				}
				else {
					$sender = api_get_user($a, null, $item['from_xchan']);
					$recipient = $user_info;
				}
	
				$ret[]=api_format_message($item, $recipient, $sender);
			}
		}
		
		$data = array('$messages' => $ret);
		switch($type){
			case "atom":
			case "rss":
				$data = api_rss_extra($a, $data, $user_info);
		}
				
		return  api_apply_template("direct_messages", $type, $data);
		
	}
	function api_direct_messages_sentbox(&$a, $type){
		return api_direct_messages_box($a, $type, "sentbox");
	}
	function api_direct_messages_inbox(&$a, $type){
		return api_direct_messages_box($a, $type, "inbox");
	}
	function api_direct_messages_all(&$a, $type){
		return api_direct_messages_box($a, $type, "all");
	}
	function api_direct_messages_conversation(&$a, $type){
		return api_direct_messages_box($a, $type, "conversation");
	}
	api_register_func('api/direct_messages/conversation','api_direct_messages_conversation',true);
	api_register_func('api/direct_messages/all','api_direct_messages_all',true);
	api_register_func('api/direct_messages/sent','api_direct_messages_sentbox',true);
	api_register_func('api/direct_messages','api_direct_messages_inbox',true);
	function api_oauth_request_token(&$a, $type){
		try{
			$oauth = new ZotOAuth1();
			$req = OAuth1Request::from_request();
			logger('Req: ' . var_export($req,true),LOGGER_DATA);
			$r = $oauth->fetch_request_token($req);
		}catch(Exception $e){
			logger('oauth_exception: ' . print_r($e->getMessage(),true));
			echo "error=". OAuth1Util::urlencode_rfc3986($e->getMessage()); 
			killme();
		}
		echo $r;
		killme();	
	}
	function api_oauth_access_token(&$a, $type){
		try{
			$oauth = new ZotOAuth1();
			$req = OAuth1Request::from_request();
			$r = $oauth->fetch_access_token($req);
		}catch(Exception $e){
			echo "error=". OAuth1Util::urlencode_rfc3986($e->getMessage()); killme();
		}
		echo $r;
		killme();			
	}
	api_register_func('api/oauth/request_token', 'api_oauth_request_token', false);
	api_register_func('api/oauth/access_token', 'api_oauth_access_token', false);
/*
Not implemented by now:
statuses/retweets_of_me
friendships/create
friendships/destroy
friendships/exists
friendships/show
account/update_location
account/update_profile_background_image
account/update_profile_image
blocks/create
blocks/destroy
Not implemented in status.net:
statuses/retweeted_to_me
statuses/retweeted_by_me
direct_messages/destroy
account/end_session
account/update_delivery_device
notifications/follow
notifications/leave
blocks/exists
blocks/blocking
lists
*/