2 require_once("bbcode.php");
3 require_once("datetime.php");
14 // functions adopted from http://www.sean-barton.co.uk/2009/03/turning-an-array-or-object-into-xml-using-php/
16 public static function generateValidXmlFromObj(stdClass $obj, $node_block='nodes', $node_name='node') {
17 $arr = get_object_vars($obj);
18 return self::generateValidXmlFromArray($arr, $node_block, $node_name);
21 public static function generateValidXmlFromArray($array, $node_block='nodes', $node_name='node') {
23 if ($array instanceof Container){
24 $node_block=$array->name;
25 foreach($array->attrs as $n=>$v){
31 $xml = '<?xml version="1.0" encoding="UTF-8" ?>';
33 $xml .= '<' . $node_block . $attrs. '>';
34 $xml .= self::generateXmlFromArray($array, $node_name);
35 $xml .= '</' . $node_block . '>';
40 private static function generateXmlFromArray($array, $node_name) {
43 if (is_array($array) || is_object($array)) {
44 foreach ($array as $key=>$value) {
46 if ($value instanceof Container){
47 $node_name=$value->name;
48 foreach($value->attrs as $n=>$v){
52 if (is_numeric($key)) {
57 $xml .= '<' . $key . $attrs.'>' . self::generateXmlFromArray($value, $node_name) . '</' . $key . '>';
60 if (is_bool($array)) $array = ($array===true?"true":"false");
61 $xml = htmlspecialchars($array, ENT_QUOTES);
69 // this is used when json and xml are not translatable to arrays
70 // like [{text:'text'},{text:'text2'}]
71 // and <statuses type='array'><status><text>text</text></status><status><text>text2</text></status></statuses>
72 class Container extends ArrayObject{
74 public $attrs=Array();
75 function __construct($name){
77 $args = func_get_args();
79 call_user_func_array(array(parent,'__construct'), $args);
83 function api_date($str){
84 //Wed May 23 06:01:13 +0000 2007
85 return datetime_convert('UTC', 'UTC', $str, "D M d h:i:s +0000 Y" );
89 function api_register_func($path, $func, $auth=false){
91 $API[$path] = array('func'=>$func,
98 function api_login(&$a){
99 if (!isset($_SERVER['PHP_AUTH_USER'])) {
100 header('WWW-Authenticate: Basic realm="Friendika"');
101 header('HTTP/1.0 401 Unauthorized');
102 die('This api require login');
105 $user = $_SERVER['PHP_AUTH_USER'];
106 $encrypted = hash('whirlpool',trim($_SERVER['PHP_AUTH_PW']));
111 // process normal login request
113 $r = q("SELECT * FROM `user` WHERE ( `email` = '%s' OR `nickname` = '%s' )
114 AND `password` = '%s' AND `blocked` = 0 AND `verified` = 1 LIMIT 1",
121 $_SESSION['uid'] = $record['uid'];
122 $_SESSION['theme'] = $record['theme'];
123 $_SESSION['authenticated'] = 1;
124 $_SESSION['page_flags'] = $record['page-flags'];
125 $_SESSION['my_url'] = $a->get_baseurl() . '/profile/' . $record['nickname'];
126 $_SESSION['addr'] = $_SERVER['REMOTE_ADDR'];
128 notice( t("Welcome back ") . $record['username'] . EOL);
131 if(strlen($a->user['timezone'])) {
132 date_default_timezone_set($a->user['timezone']);
133 $a->timezone = $a->user['timezone'];
136 $r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1",
137 intval($_SESSION['uid']));
140 $a->cid = $r[0]['id'];
141 $_SESSION['cid'] = $a->cid;
143 q("UPDATE `user` SET `login_date` = '%s' WHERE `uid` = %d LIMIT 1",
144 dbesc(datetime_convert()),
145 intval($_SESSION['uid'])
148 call_hooks('logged_in', $a->user);
150 header('X-Account-Management-Status: active; name="' . $a->user['username'] . '"; id="' . $a->user['nickname'] .'"');
153 function api_call(&$a){
155 foreach ($API as $p=>$info){
156 if (strpos($a->query_string, $p)===0){
157 if ($info['auth']===true) api_login($a);
159 $r = call_user_func($info['func'], $a);
160 if ($r===false) return;
162 if ($r instanceof Container){
163 $name=NULL; $values=$r;
165 foreach($r as $name=>$values){}
169 if (strpos($a->query_string, ".xml")>0){
170 header ("Content-Type: text/xml");
171 return XMLSerializer::generateValidXmlFromArray($values, $name);
174 if (strpos($a->query_string, ".json")>0){
175 header ("Content-Type: application/json");
176 if ($values instanceof Container) $values= iterator_to_array($values);
177 return json_encode($values);
179 //echo "<pre>"; var_dump($r); die();
185 * Returns user info array
187 function api_get_user(&$a){
190 if(x($_GET, 'user_id')) {
191 $user = intval($_GET['user_id']);
192 $extra_query = "AND `user`.`uid` = %d ";
194 if(x($_GET, 'screen_name')) {
195 $user = dbesc($_GET['screen_name']);
196 $extra_query = "AND `user`.`nickname` = '%s' ";
200 list($user, $null) = explode(".",$a->argv[3]);
201 if(is_numeric($user)){
202 $user = intval($user);
203 $extra_query = "AND `user`.`uid` = %d ";
205 $user = dbesc($user);
206 $extra_query = "AND `user`.`nickname` = '%s' ";
211 if (local_user()===false) {
212 api_login($a); return False;
214 $user = $_SESSION['uid'];
215 $extra_query = "AND `user`.`uid` = %d ";
222 $uinfo = q("SELECT * FROM `user`, `contact`
223 WHERE `user`.`uid`=`contact`.`uid` AND `contact`.`self`=1
227 if (count($uinfo)==0) {
231 // count public wall messages
232 $r = q("SELECT COUNT(`id`) as `count` FROM `item`
235 AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`=''",
236 intval($uinfo[0]['uid'])
238 $countitms = $r[0]['count'];
241 $r = q("SELECT COUNT(`id`) as `count` FROM `contact`
243 AND `self`=0 AND `blocked`=0",
244 intval($uinfo[0]['uid'])
246 $countfriends = $r[0]['count'];
250 'id' => $uinfo[0]['uid'],
251 'name' => $uinfo[0]['username'],
252 'screen_name' => $uinfo[0]['nickname'],
253 'location' => $uinfo[0]['default-location'],
254 'profile_image_url' => $uinfo[0]['photo'],
255 'url' => $uinfo[0]['url'],
256 'protected' => false, #
257 'friends_count' => $countfriends,
258 'created_at' => api_date($uinfo[0]['created']),
259 'utc_offset' => 0, #XXX: fix me
260 'time_zone' => $uinfo[0]['timezone'],
261 'geo_enabled' => false,
262 'statuses_count' => $countitms, #XXX: fix me
263 'lang' => 'en', #XXX: fix me
265 'followers_count' => $countfriends, #XXX: fix me
266 'lang' => 'en', #XXX: fix me
267 'favourites_count' => 0,
268 'contributors_enabled' => false,
269 'follow_request_sent' => false,
270 'profile_background_color' => 'cfe8f6',
271 'profile_text_color' => '000000',
272 'profile_link_color' => 'FF8500',
273 'profile_sidebar_fill_color' =>'AD0066',
274 'profile_sidebar_border_color' => 'AD0066',
275 'profile_background_image_url' => '',
276 'profile_background_tile' => false,
277 'profile_use_background_image' => false,
278 'notifications' => false,
290 * Returns an HTTP 200 OK response code and a representation of the requesting user if authentication was successful;
291 * returns a 401 status code and an error message if not.
292 * http://developer.twitter.com/doc/get/account/verify_credentials
294 function api_account_verify_credentials(&$a){
295 if (local_user()===false) return false;
296 $user_info = api_get_user($a);
297 $ret = new Container("user", $user_info);
300 api_register_func('api/account/verify_credentials','api_account_verify_credentials', true);
305 * Returns extended information of a given user, specified by ID or screen name as per the required id parameter.
306 * The author's most recent status will be returned inline.
307 * http://developer.twitter.com/doc/get/users/show
309 function api_users_show(&$a){
310 $user_info = api_get_user($a);
312 // get last public wall message
313 $lastwall = q("SELECT * FROM `item`
316 AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`=''
317 ORDER BY `created` DESC LIMIT 1",
318 intval($user_info['uid'])
321 //echo "<pre>"; var_dump($lastwall); die();
323 $user_info['status'] = array(
324 'created_at' => api_date($lastwall[0]['created']),
325 'id' => $lastwall[0]['id'],
326 'text' => bbcode($lastwall[0]['body']),
328 'truncated' => false,
329 'in_reply_to_status_id' => '',
330 'in_reply_to_user_id' => '',
331 'favorited' => false,
332 'in_reply_to_screen_name' => '',
334 'coordinates' => $lastwall[0]['coord'],
335 'place' => $lastwall[0]['location'],
339 $ret = Array('user' => $user_info);
344 api_register_func('api/users/show','api_users_show');
348 * http://developer.twitter.com/doc/get/statuses/home_timeline
350 function api_statuses_home_timeline(&$a){
351 if (local_user()===false) return false;
353 $user_info = api_get_user($a);
355 // get last newtork messages
356 $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE `id` = `parent` ) ";
358 $r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
359 `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
360 `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
361 `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
362 FROM `item`, `contact`, `user`
363 WHERE `item`.`uid` = %d AND `user`.`uid` = `item`.`uid`
364 AND `item`.`visible` = 1 AND `item`.`deleted` = 0
365 AND `contact`.`id` = `item`.`contact-id`
366 AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
368 ORDER BY `item`.`created` DESC LIMIT %d ,%d ",
369 intval($user_info['id']),
372 $ret = new Container("statuses");
373 $ret->attrs['type']='array';
375 foreach($r as $item) {
376 $status = new Container('status', array(
377 'created_at'=> api_date($item['created']),
379 'text' => strip_tags(bbcode($item['body'])),
380 'source' => 'web', #XXX: Fix me!
381 'truncated' => False,
382 'in_reply_to_status_id' => ($item['parent']!=$item['id']?$item['id']:''),
383 'in_reply_to_user_id' => '',
384 'favorited' => false,
385 'in_reply_to_screen_name' => '',
387 'coordinates' => $item['coord'],
388 'place' => $item['location'],
389 'contributors' => '',
400 api_register_func('api/statuses/home_timeline','api_statuses_home_timeline', true);
403 * http://developer.twitter.com/doc/get/statuses/user_timeline
405 function api_statuses_user_timeline(&$a){
407 $user_info = api_get_user($a);
409 // get last public wall message
410 $lastwall = q("SELECT `item`.*, `item`.`id` AS `item_id`,
411 `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
412 `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
413 `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
414 FROM `item`, `contact`, `user`
415 WHERE `item`.`uid` = %d AND `user`.`uid` = `item`.`uid`
416 AND `item`.`visible` = 1 AND `item`.`deleted` = 0
417 AND `contact`.`id` = `item`.`contact-id`
418 AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
420 AND `item`.`type`='wall'
421 AND `item`.`allow_cid`='' AND `item`.`allow_gid`='' AND `item`.`deny_cid`='' AND `item`.`deny_gid`=''
423 ORDER BY `item`.`created` DESC LIMIT %d ,%d ",
424 intval($user_info['id']),
429 $ret = new Container("statuses");
430 $ret->attrs['type']='array';
432 foreach($lastwall as $item) {
433 $status = new Container('status', array(
434 'created_at'=> api_date($item['created']),
436 'text' => strip_tags(bbcode($item['body'])),
437 'source' => 'web', #XXX: Fix me!
438 'truncated' => False,
439 'in_reply_to_status_id' => '',
440 'in_reply_to_user_id' => '',
441 'favorited' => false,
442 'in_reply_to_screen_name' => '',
444 'coordinates' => $item['coord'],
445 'place' => $item['location'],
446 'contributors' => '',
456 api_register_func('api/statuses/user_timeline','api_statuses_user_timeline', true);