PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/api/includes/ringside/api/OpenFBServer.php

https://github.com/jkinner/ringside
PHP | 390 lines | 267 code | 41 blank | 82 comment | 33 complexity | 463e41caffd1d45f82fadd7930256213 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
  1. <?php
  2. /*******************************************************************************
  3. * Ringside Networks, Harnessing the power of social networks.
  4. *
  5. * Copyright 2008 Ringside Networks, Inc., and individual contributors as indicated
  6. * by the @authors tag or express copyright attribution
  7. * statements applied by the authors. All third-party contributions are
  8. * distributed under license by Ringside Networks, Inc.
  9. *
  10. * This is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU Lesser General Public License as
  12. * published by the Free Software Foundation; either version 2.1 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This software is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this software; if not, write to the Free
  22. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  23. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  24. ******************************************************************************/
  25. //require_once( 'ringside/api/OpenFBAPIException.php' );
  26. //require_once( 'ringside/api/AbstractRest.php' );
  27. //require_once( 'ringside/api/RequestContext.php' );
  28. //require_once( 'ringside/api/facebook/OpenFBConstants.php' );
  29. require_once( 'ringside/api/config/RingsideApiConfig.php' );
  30. //require_once( 'ringside/api/Session.php' );
  31. //require_once( 'ringside/m3/event/DispatcherFactory.php' );
  32. /**
  33. * Implements the OpenFB auth.getSession API.
  34. *
  35. * @author Richard Friedman
  36. */
  37. class OpenFBServer {
  38. public static function errorHandler($errno, $errstr, $file, $line, $stack) {
  39. error_log("Unexpected error at $file:$line: ".var_export($stack));
  40. throw new Exception(
  41. $errstr,
  42. $errno,
  43. $file,
  44. $line,
  45. $stack
  46. );
  47. }
  48. /**
  49. * Process a Request.
  50. *
  51. *
  52. * There are a few different type's of method calls currently.
  53. * 1. Auth related methods, which all start with "auth.". These
  54. * methods do not yet typically have a session key or in process of creating/validating/removing one.
  55. * Other inner/inter systems security methods can be here as well. Note, you should NOT add a method
  56. * to authenticate a user, that should be done else where. Use the inner-method of approveToken and lock
  57. * it down within a system.
  58. *
  59. * 2. Application method calls. This is really the catchalll and executes the request handling mechanism.
  60. *
  61. * 3. Systems Management calls. (coming soon).
  62. *
  63. */
  64. function execute( $request ) {
  65. ini_set( 'session.use_cookies', '0' );
  66. ini_set('session.save_handler', 'user');
  67. session_set_save_handler(array('Session', 'open'),
  68. array('Session', 'close'),
  69. array('Session', 'read'),
  70. array('Session', 'write'),
  71. array('Session', 'destroy'),
  72. array('Session', 'gc')
  73. );
  74. session_cache_limiter( 'none' );
  75. set_error_handler(array('OpenFBServer', 'errorHandler'), E_ERROR);
  76. // There is a change dependending on magic quotes settings
  77. // that PHP will add in extra slashes, not good for us.
  78. // This is removed as of PHP 6 as well.
  79. if( get_magic_quotes_gpc() ) {
  80. foreach ($request as $rname => $rval) {
  81. $request[$rname] = stripslashes($rval);
  82. }
  83. }
  84. $context = Api_RequestContext::createRequestContext( $request );
  85. if ( $context->getNetworkKey() == null ) {
  86. $keyService = Api_Bo_KeyService::create();
  87. $ids = $keyService->getIds($context->getApiKey());
  88. $domain_keys = $keyService->getKeyset($ids['domain_id'], $ids['domain_id']);
  89. if ( $domain_keys != null ) {
  90. $context->setNetworkKey($domain_keys['api_key']);
  91. }
  92. }
  93. //error_log( "method $method requested" );
  94. try {
  95. $response = $this->executeRequest( $context, $request );
  96. $this->send_response( $context->getMethod(), $response, $context->getFormat(), $context->getCallback());
  97. } catch (Exception $exception) {
  98. error_log("When executing {$context->getMethod()} request in OpenFBServer: ".$exception->getMessage());
  99. error_log($exception->getTraceAsString());
  100. $this->send_exception( $exception, $request, $context->getFormat(), $context->getCallback());
  101. }
  102. // TODO - This would hurt infinite session concepts, should we just bag this concept?
  103. // Should session cache be extended after each call?
  104. // Should it be validated against expires time in session?
  105. // session_cache_expire ( 24 * 60 );
  106. }
  107. /**
  108. * Execute the request and return the hash results, this
  109. * was separated soley for the purpose of running test cases.
  110. *
  111. * @param unknown_type $requestParams
  112. */
  113. function executeRequest( Api_RequestContext &$context ) {
  114. $response = array();
  115. if ( $context->getMethod() == null ) {
  116. throw new OpenFBAPIException( 'Incorrect Signature, Missing METHOD.', FB_ERROR_CODE_INCORRECT_SIGNATURE );
  117. }
  118. // Call the object/method.
  119. $api_name = explode( '.', $context->getMethod() );
  120. $api_pkg = $api_name[1];
  121. $api_class = ucfirst($api_name[1]) . ucfirst($api_name[2]);
  122. $lasterrorlevel = error_reporting(E_ERROR);
  123. if ( ! include_once( $api_name[0].'/rest/'.$api_class.'.php' ) ) {
  124. // TODO: Move these to match the packaging standard
  125. // Default OpenFBServer API implementations are still here
  126. include_once( 'ringside/api/facebook/' . $api_class . '.php' );
  127. }
  128. error_reporting($lasterrorlevel);
  129. if ( ! $api_class ) {
  130. throw new Exception("Class $api_class could not be loaded");
  131. }
  132. $faf = new $api_class();
  133. // Set the server object.
  134. $faf->_setServer( $this );
  135. // set the context
  136. $faf->_setContext( $context );
  137. // Load the session and setup the session.
  138. $faf->loadSession ( );
  139. // Execute delegation?
  140. $faf->delegateRequest();
  141. // Validation steps
  142. $faf->validateSession();
  143. $faf->validateApiKey();
  144. $faf->validateSig( );
  145. $faf->validateVersion( );
  146. $faf->validateCallId( );
  147. $faf->validateRequest( );
  148. // let's invoke the API that is being requested - collect stat around the call
  149. $tuple = new M3_Event_Tuple( $faf->getNetworkId(), $faf->getAppId(), $faf->getUserId() );
  150. $dispatcher = M3_Event_DispatcherFactory::createApiResponseTimeTupleDispatcher($context->getMethod(), $tuple);
  151. $dispatcher->startTimer();
  152. $response = $faf->execute( );
  153. $dispatcher->stopTimer(); // emit event
  154. return $response;
  155. }
  156. function send_exception( $exception, $request, $format, $callback ) {
  157. $response = array( 'error_code'=>$exception->getCode(),
  158. 'error_msg'=>$exception->getMessage());
  159. //'error_trace'=>$exception->getTraceAsString() );
  160. $args = array();
  161. foreach ( $request as $key=>$value ) {
  162. $args[] = array ( "key"=>$key, "value"=>$value );
  163. }
  164. $response['request_args'] = array("arg"=>$args);
  165. $this->send_response( 'error', $response, $format, $callback );
  166. }
  167. /**
  168. * Prescribed mechanism for sending/formatting REST response.
  169. * XML Response needs work for custom XML returns.
  170. *
  171. * @param unknown_type $method
  172. * @param unknown_type $response
  173. */
  174. function send_response ( $method, $response, $format, $callback ) {
  175. // based on format respond back
  176. if ( $format == 'json' ) {
  177. if ( $callback != null ) print "$callback(";
  178. $crest = $response;
  179. if (is_array($response)) $crest = current($response);
  180. if ((count($response) == 1) && !is_array($crest)) {
  181. print "\"$crest\"";
  182. } else {
  183. self::printJSON($response);
  184. }
  185. if ( $callback != null ) print ");";
  186. } else if ( $format == 'php' ) {
  187. print_r( $response );
  188. } else if ( $format == 'html' ) {
  189. echo 'Method Response : <b> '.str_replace( '.', '_', $method).'</b><br />';
  190. if ( count($response) == 1 && !is_array( current($response) ) ) {
  191. echo current($response);
  192. } else {
  193. array_walk( $response, array('OpenFBServer','printHTML'), '' );
  194. }
  195. echo 'End of response <b>'.str_replace( '.', '_', $method).'</b><br />';
  196. } else if ( $callback != null ) {
  197. echo $callback . "('" . addslashes('<?xml version="1.0" encoding="UTF-8"?>');
  198. $api_name = explode( '.', $method );
  199. $methodResponse = ((sizeof($api_name) == 3)?$api_name[1].'_'.$api_name[2]:$method).'_response';
  200. echo addslashes( '<'.$methodResponse.'>' );
  201. if ( count($response) == 1 && !is_array( current($response) ) ) {
  202. echo addslashes(current($response));
  203. } else {
  204. array_walk( $response, array('OpenFBServer','printXML'), '' );
  205. }
  206. echo addslashes( '</' . $methodResponse . '>');
  207. } else {
  208. $api_name = explode( '.', $method );
  209. $methodResponse = ((sizeof($api_name) == 3)?$api_name[1].'_'.$api_name[2]:$method).'_response';
  210. echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
  211. $crest = $response;
  212. if (is_array($response)) $crest = current($response);
  213. if ( count($response) == 1 && !is_array($crest) ) {
  214. $result = $crest;
  215. echo "<$methodResponse>$result</$methodResponse>";
  216. } else if ( count($response) == 1 ) {
  217. $result = current($response);
  218. $list = '';
  219. if ( isset( $result[0]) ){
  220. $list = " list=\"true\"";
  221. }
  222. echo "<$methodResponse" . "$list>";
  223. array_walk( $response, array('OpenFBServer','printXML'), '' );
  224. echo "</$methodResponse>";
  225. } else {
  226. echo "<$methodResponse>";
  227. array_walk( $response, array('OpenFBServer','printXML'), '' );
  228. echo "</$methodResponse>";
  229. }
  230. }
  231. }
  232. function printJSON($arr)
  233. {
  234. if (!is_array($arr)) {
  235. if (!is_int($arr)) print "\"";
  236. print $arr;
  237. if (!is_int($arr)) print "\"";
  238. return;
  239. }
  240. $pbrak = true;
  241. if ((count($arr) == 1) && !self::is_assoc(current($arr))) $pbrak = false;
  242. if ($pbrak) print "{";
  243. $first = true;
  244. foreach ($arr as $key => $val) {
  245. if (!$first) print ",";
  246. else $first = false;
  247. if (!is_array($val)) {
  248. print "\"$key\":";
  249. if (!is_int($val)) print "\"";
  250. print $val;
  251. if (!is_int($val)) print "\"";
  252. } else {
  253. if (self::is_assoc($val)) {
  254. print "\"$key\":";
  255. self::printJSON($val);
  256. } else {
  257. $first2 = true;
  258. print "[";
  259. foreach ($val as $val2) {
  260. if (!$first2) print ",";
  261. else $first2 = false;
  262. self::printJSON($val2);
  263. }
  264. print "]";
  265. }
  266. }
  267. }
  268. if ($pbrak) print "}";
  269. }
  270. //brute force method to check whether
  271. //an array is associativae
  272. function is_assoc($arr)
  273. {
  274. foreach ($arr as $key => $val) {
  275. if (!is_int($key)) return true;
  276. }
  277. return false;
  278. }
  279. function printHTML( $value, $key, $parent_key) {
  280. if ( is_int( $key ) ) {
  281. $key = $parent_key ;
  282. }
  283. if ( empty( $value ) ) {
  284. echo "Key is Empty : <b>$key</b><br>";
  285. } else if ( is_array( $value ) ) {
  286. if ( !is_int( key( $value ) ) ) {
  287. echo "$key is array : <br /><table border='1'><tr><td>";
  288. array_walk($value, array('OpenFBServer','printHTML'), $key );
  289. echo "</td></tr></table> end of $key array<br />";
  290. } else {
  291. array_walk($value, array('OpenFBServer','printHTML'), $key );
  292. }
  293. } else {
  294. echo "$key : $value<br/>";
  295. }
  296. }
  297. /**
  298. * Helper function to print array as XML.
  299. * [TODO] Support arrays of arrays.
  300. * TODO Support encoding for callback
  301. *
  302. * @param unknown_type $value
  303. * @param unknown_type $key
  304. */
  305. static function printXML( $value, $key, $parent_key ) {
  306. if ( is_int( $key ) ) {
  307. $key = $parent_key ;
  308. }
  309. if ( is_array( $value ) ) {
  310. if ( !is_int( key( $value ) ) ) {
  311. $list = '';
  312. if ( count($value) == 1 ) {
  313. $current = current($value);
  314. if ( is_array($current) && isset( $current[0] ) ) {
  315. $list = " list=\"true\"";
  316. }
  317. }
  318. echo "<$key"."$list>". "\n";
  319. array_walk($value, array('OpenFBServer','printXML'), $key );
  320. echo "</$key>". "\n";
  321. } else {
  322. array_walk($value, array('OpenFBServer','printXML'), $key );
  323. }
  324. } else if ( strlen($value) == 0 ) {
  325. echo "<$key />". "\n";
  326. } else {
  327. //echo "<$key>" . htmlentities($value) . "</$key>". "\n";
  328. echo "<$key>" . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . "</$key>". "\n";
  329. }
  330. }
  331. }
  332. ?>