]> git.mxchange.org Git - friendica.git/blob - include/api.php
work on api.
[friendica.git] / include / api.php
1 <?php
2         require_once("bbcode.php");
3         require_once("datetime.php");
4         
5         /* 
6          * Twitter-Like API
7          *  
8          */
9
10         $API = Array();
11          
12         class XMLSerializer {
13         
14             // functions adopted from http://www.sean-barton.co.uk/2009/03/turning-an-array-or-object-into-xml-using-php/
15         
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);
19             }
20         
21             public static function generateValidXmlFromArray($array, $node_block='nodes', $node_name='node') {
22                         $attrs="";
23                         if ($array instanceof Container){
24                                 $node_block=$array->name;
25                                 foreach($array->attrs as $n=>$v){
26                                         $attrs .= " $n='$v'";
27                                 }
28                         }
29         
30         
31                 $xml = '<?xml version="1.0" encoding="UTF-8" ?>';
32         
33                 $xml .= '<' . $node_block . $attrs. '>';
34                 $xml .= self::generateXmlFromArray($array, $node_name);
35                 $xml .= '</' . $node_block . '>';
36         
37                 return $xml;
38             }
39         
40             private static function generateXmlFromArray($array, $node_name) {
41                 $xml = '';
42                                 
43                 if (is_array($array) || is_object($array)) {
44                     foreach ($array as $key=>$value) {
45                         $attrs="";
46                                         if ($value instanceof Container){
47                                                 $node_name=$value->name;
48                                                 foreach($value->attrs as $n=>$v){
49                                                         $attrs .= " $n='$v'";
50                                                 }
51                                         }                               
52                         if (is_numeric($key)) {
53                             $key = $node_name;
54                         }
55         
56         
57                         $xml .= '<' . $key . $attrs.'>' . self::generateXmlFromArray($value, $node_name) . '</' . $key . '>';
58                     }
59                 } else {
60                         if (is_bool($array)) $array = ($array===true?"true":"false");
61                     $xml = htmlspecialchars($array, ENT_QUOTES);
62                 }
63         
64                 return $xml;
65             }
66         
67         }
68         
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{
73                 public $name;
74                 public $attrs=Array();
75                 function __construct($name){
76                         $this->name = $name;
77                         $args = func_get_args();
78                         unset($args[0]);
79                         call_user_func_array(array(parent,'__construct'), $args);
80                 }
81         }
82         
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" );
86         }
87          
88         
89         function api_register_func($path, $func, $auth=false){
90                 global $API;
91                 $API[$path] = array('func'=>$func,
92                                                         'auth'=>$auth);
93         }
94         
95         /**
96          * Simple HTTP Login
97          */
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');
103                 }
104                 
105                 $user = $_SERVER['PHP_AUTH_USER'];
106                 $encrypted = hash('whirlpool',trim($_SERVER['PHP_AUTH_PW']));
107                 
108                 
109                         // da auth.php
110                 
111                 // process normal login request
112
113                 $r = q("SELECT * FROM `user` WHERE ( `email` = '%s' OR `nickname` = '%s' ) 
114                         AND `password` = '%s' AND `blocked` = 0 AND `verified` = 1 LIMIT 1",
115                         dbesc(trim($user)),
116                         dbesc(trim($user)),
117                         dbesc($encrypted)
118                 );
119                 if(count($r))
120                         $record = $r[0];
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'];
127
128                 notice( t("Welcome back ") . $record['username'] . EOL);
129                 $a->user = $record;
130
131                 if(strlen($a->user['timezone'])) {
132                         date_default_timezone_set($a->user['timezone']);
133                         $a->timezone = $a->user['timezone'];
134                 }
135
136                 $r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1",
137                         intval($_SESSION['uid']));
138                 if(count($r)) {
139                         $a->contact = $r[0];
140                         $a->cid = $r[0]['id'];
141                         $_SESSION['cid'] = $a->cid;
142                 }
143                 q("UPDATE `user` SET `login_date` = '%s' WHERE `uid` = %d LIMIT 1",
144                         dbesc(datetime_convert()),
145                         intval($_SESSION['uid'])
146                 );
147
148                 call_hooks('logged_in', $a->user);
149
150                 header('X-Account-Management-Status: active; name="' . $a->user['username'] . '"; id="' . $a->user['nickname'] .'"');
151         }
152         
153         function api_call(&$a){
154                 GLOBAL $API;
155                 foreach ($API as $p=>$info){
156                         if (strpos($a->query_string, $p)===0){
157                                 if ($info['auth']===true) api_login($a);
158                                 
159                                 $r = call_user_func($info['func'], $a);
160                                 if ($r===false) return;
161                                 
162                                 if ($r instanceof Container){
163                                         $name=NULL; $values=$r;
164                                 } else {                                                
165                                         foreach($r as $name=>$values){}
166                                 }
167                                 
168                                 // return xml
169                                 if (strpos($a->query_string, ".xml")>0){
170                                         header ("Content-Type: text/xml");  
171                                         return XMLSerializer::generateValidXmlFromArray($values, $name);
172                                 }
173                                 // return json
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);
178                                 }
179                                 //echo "<pre>"; var_dump($r); die();
180                         }
181                 }
182                 return false;
183         }
184         /**
185          * Returns user info array
186          */
187         function api_get_user(&$a){
188                 $user = null;
189                 $extra_query = "";
190                 if(x($_GET, 'user_id')) {
191                         $user = intval($_GET['user_id']);       
192                         $extra_query = "AND `user`.`uid` = %d ";
193                 }
194                 if(x($_GET, 'screen_name')) {
195                         $user = dbesc($_GET['screen_name']);    
196                         $extra_query = "AND `user`.`nickname` = '%s' ";
197                 }
198                 
199                 if ($user===null){
200                         list($user, $null) = explode(".",$a->argv[3]);
201                         if(is_numeric($user)){
202                                 $user = intval($user);
203                                 $extra_query = "AND `user`.`uid` = %d ";
204                         } else {
205                                 $user = dbesc($user);
206                                 $extra_query = "AND `user`.`nickname` = '%s' ";
207                         }
208                 }
209                 
210                 if ($user==='') {
211                         if (local_user()===false) {
212                                 api_login($a); return False;
213                         } else {
214                                 $user = $_SESSION['uid'];
215                                 $extra_query = "AND `user`.`uid` = %d ";
216                         }
217                         
218                 }
219                 
220
221                 // user info            
222                 $uinfo = q("SELECT * FROM `user`, `contact`
223                                 WHERE `user`.`uid`=`contact`.`uid` AND `contact`.`self`=1
224                                 $extra_query",
225                                 $user
226                 );
227                 if (count($uinfo)==0) {
228                         return False;
229                 }
230                 
231                 // count public wall messages
232                 $r = q("SELECT COUNT(`id`) as `count` FROM `item`
233                                 WHERE  `uid` = %d
234                                 AND `type`='wall' 
235                                 AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`=''",
236                                 intval($uinfo[0]['uid'])
237                 );
238                 $countitms = $r[0]['count'];
239                 
240                 // count friends
241                 $r = q("SELECT COUNT(`id`) as `count` FROM `contact`
242                                 WHERE  `uid` = %d
243                                 AND `self`=0 AND `blocked`=0", 
244                                 intval($uinfo[0]['uid'])
245                 );
246                 $countfriends = $r[0]['count'];
247                                 
248
249                 $ret = Array(
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
264                         'description' => '',
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,        
279                 );
280                 
281                 return $ret;
282                 
283         }
284         
285         /**
286          ** TWITTER API
287          */
288         
289         /**
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
293          */
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);
298                 return $ret;
299         }
300         api_register_func('api/account/verify_credentials','api_account_verify_credentials', true);
301                 
302         
303                 
304         /**
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
308          */
309         function api_users_show(&$a){
310                 $user_info = api_get_user($a);
311                 
312                 // get last public wall message
313                 $lastwall = q("SELECT * FROM `item`
314                                 WHERE  `uid` = %d
315                                 AND `type`='wall' 
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'])
319                 );
320         
321                 //echo "<pre>"; var_dump($lastwall); die();
322                 
323                 $user_info['status'] = array(
324                         'created_at' => api_date($lastwall[0]['created']),
325                         'id' => $lastwall[0]['id'],
326                         'text' => bbcode($lastwall[0]['body']),
327                         'source' => 'web',
328                         'truncated' => false,
329                         'in_reply_to_status_id' => '',
330                         'in_reply_to_user_id' => '',
331                         'favorited' => false,
332                         'in_reply_to_screen_name' => '',
333                         'geo' => '',
334                         'coordinates' => $lastwall[0]['coord'],
335                         'place' => $lastwall[0]['location'],
336                         'contributors' => ''                                    
337                 );
338
339                 $ret = Array('user' => $user_info);
340                 
341                 return $ret;
342                 
343         }
344         api_register_func('api/users/show','api_users_show');
345         
346         /**
347          * 
348          * http://developer.twitter.com/doc/get/statuses/home_timeline
349          */
350         function api_statuses_home_timeline(&$a){
351                 if (local_user()===false) return false;
352                 
353                 $user_info = api_get_user($a);
354                 
355                 // get last newtork messages
356                 $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE `id` = `parent` ) ";
357                 
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
367                         $sql_extra
368                         ORDER BY `item`.`created` DESC LIMIT %d ,%d ",
369                         intval($user_info['id']),
370                         0,20
371                 );
372                 $ret = new Container("statuses");
373                 $ret->attrs['type']='array';
374
375                 foreach($r as $item) {
376                         $status = new Container('status', array(
377                                 'created_at'=> api_date($item['created']),
378                                 'id'            => $item['id'],
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' => '',
386                                 'geo' => '',
387                                 'coordinates' => $item['coord'],
388                                 'place' => $item['location'],
389                                 'contributors' => '',
390                                 'annotations'  => '',
391                                 'entities'  => '',
392                                 'user' => $user_info                            
393                         
394                         ));
395                         $ret[]=$status;
396                 };
397                 
398                 return $ret;
399         }
400         api_register_func('api/statuses/home_timeline','api_statuses_home_timeline', true);
401         
402         /*
403          * http://developer.twitter.com/doc/get/statuses/user_timeline
404          */
405         function api_statuses_user_timeline(&$a){
406                         
407                 $user_info = api_get_user($a);
408                 
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
419                         
420                         AND `item`.`type`='wall' 
421                         AND `item`.`allow_cid`='' AND `item`.`allow_gid`='' AND `item`.`deny_cid`='' AND `item`.`deny_gid`=''
422                         
423                         ORDER BY `item`.`created` DESC LIMIT %d ,%d ",
424                         intval($user_info['id']),
425                         0, 20
426                 );
427                 
428                 
429                 $ret = new Container("statuses");
430                 $ret->attrs['type']='array';
431                 
432                 foreach($lastwall as $item) {
433                         $status = new Container('status', array(
434                                 'created_at'=> api_date($item['created']),
435                                 'id'            => $item['id'],
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' => '',
443                                 'geo' => '',
444                                 'coordinates' => $item['coord'],
445                                 'place' => $item['location'],
446                                 'contributors' => '',
447                                 'annotations'  => '',
448                                 'entities'  => '',
449                                 'user' => $user_info
450                         ));
451                         $ret[]=$status;
452                 };
453                 
454                 return $ret;
455         }
456         api_register_func('api/statuses/user_timeline','api_statuses_user_timeline', true);
457