PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/framework/php/classes/core/CASHSystem.php

https://github.com/letolabs/DIY
PHP | 521 lines | 356 code | 27 blank | 138 comment | 83 complexity | 9d0b13450d9d8b772327cbd9afe0e6de MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /**
  3. * An abstract collection of lower level static functions that are useful
  4. * across other classes.
  5. *
  6. * @package diy.org.cashmusic
  7. * @author CASH Music
  8. * @link http://cashmusic.org/
  9. *
  10. * Copyright (c) 2011, CASH Music
  11. * Licensed under the Affero General Public License version 3.
  12. * See http://www.gnu.org/licenses/agpl-3.0.html
  13. *
  14. */abstract class CASHSystem {
  15. /**
  16. * Handle annoying environment issues like magic quotes, constants and
  17. * auto-loaders before firing up the CASH platform and whatnot
  18. *
  19. * @return array
  20. */public static function startUp() {
  21. // remove magic quotes, never call them "magic" in front of your friends
  22. if (get_magic_quotes_gpc()) {
  23. function stripslashes_from_gpc(&$value) {$value = stripslashes($value);}
  24. $gpc = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
  25. array_walk_recursive($gpc, 'stripslashes_from_gpc');
  26. unset($gpc);
  27. }
  28. // define constants (use sparingly!)
  29. $root = realpath(dirname(__FILE__) . '/../..');
  30. define('CASH_PLATFORM_ROOT', $root);
  31. $cash_settings = CASHSystem::getSystemSettings();
  32. define('CASH_API_URL', $cash_settings['apilocation']);
  33. define('CASH_PUBLIC_URL',str_replace('api/','public/',$cash_settings['apilocation']));
  34. // set up auto-load
  35. spl_autoload_register('CASHSystem::autoloadClasses');
  36. // set timezone
  37. date_default_timezone_set($cash_settings['timezone']);
  38. // fire off new CASHRequest to cover any immediate-need things like GET
  39. // asset requests, etc...
  40. $cash_page_request = new CASHRequest();
  41. if (!empty($cash_page_request->response)) {
  42. $cash_page_request->sessionSet(
  43. 'initial_page_request',
  44. array(
  45. 'request' => $cash_page_request->request,
  46. 'response' => $cash_page_request->response,
  47. 'status_uid' => $cash_page_request->response['status_uid']
  48. ),
  49. 'script'
  50. );
  51. }
  52. unset($cash_page_request);
  53. }
  54. /**
  55. * The main public method to embed elements. Notice that it echoes rather
  56. * than returns, because it's meant to be used simply by calling and spitting
  57. * out the needed code...
  58. *
  59. * @return none
  60. */public static function embedElement($element_id) {
  61. // fire up the platform sans-direct-request to catch any GET/POST info sent
  62. // in to the page
  63. $cash_page_request = new CASHRequest(null);
  64. $initial_page_request = $cash_page_request->sessionGet('initial_page_request','script');
  65. if ($initial_page_request && isset($initial_page_request['request']['element_id'])) {
  66. // now test that the initial POST/GET was targeted for this element:
  67. if ($initial_page_request['request']['element_id'] == $element_id) {
  68. $status_uid = $initial_page_request['response']['status_uid'];
  69. $original_request = $initial_page_request['request'];
  70. $original_response = $initial_page_request['response'];
  71. } else {
  72. $status_uid = false;
  73. $original_request = false;
  74. $original_response = false;
  75. }
  76. } else {
  77. $status_uid = false;
  78. $original_request = false;
  79. $original_response = false;
  80. }
  81. $cash_body_request = new CASHRequest(
  82. array(
  83. 'cash_request_type' => 'element',
  84. 'cash_action' => 'getmarkup',
  85. 'id' => $element_id,
  86. 'status_uid' => $status_uid,
  87. 'original_request' => $original_request,
  88. 'original_response' => $original_response
  89. )
  90. );
  91. if ($cash_body_request->response['status_uid'] == 'element_getmarkup_400') {
  92. echo '<div class="cash_system_error">Element #' . $element_id . ' could not be found.</div>';
  93. }
  94. if (is_string($cash_body_request->response['payload'])) {
  95. echo '<div class="cash_element cash_element_' . $element_id . '">' . $cash_body_request->response['payload'] . '</div>';
  96. }
  97. if ($cash_body_request->sessionGet('initialized_element_' . $element_id,'script')) {
  98. if (ob_get_level()) {
  99. ob_flush();
  100. }
  101. }
  102. unset($cash_page_request);
  103. unset($cash_body_request);
  104. }
  105. /**
  106. * Gets the contents from a URL. First tries file_get_contents then cURL.
  107. * If neither of those work, then the server asks a friend to print out the
  108. * page at the URL and mail it to the data center. Since this takes a couple
  109. * days we return false, but that's taking nothing away from the Postal
  110. * service. They've got a hard job, so say thank you next time you get some
  111. * mail from the postman.
  112. *
  113. * @return string
  114. */public static function getURLContents($data_url,$post_data=false,$ignore_errors=false) {
  115. $url_contents = false;
  116. $user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:7.0) Gecko/20100101 Firefox/7.0';
  117. $do_post = is_array($post_data);
  118. if ($do_post) {
  119. $post_query = http_build_query($post_data);
  120. $post_length = count($post_data);
  121. }
  122. if (ini_get('allow_url_fopen')) {
  123. // try with fopen wrappers
  124. $options = array(
  125. 'http' => array(
  126. 'user_agent' => $user_agent
  127. ));
  128. if ($do_post) {
  129. $options['http']['method'] = 'POST';
  130. $options['http']['content'] = $post_query;
  131. }
  132. if ($ignore_errors) {
  133. $options['http']['ignore_errors'] = true;
  134. }
  135. $context = stream_context_create($options);
  136. $url_contents = @file_get_contents($data_url,false,$context);
  137. } elseif (in_array('curl', get_loaded_extensions())) {
  138. // fall back to cURL
  139. $ch = curl_init();
  140. $timeout = 20;
  141. @curl_setopt($ch,CURLOPT_URL,$data_url);
  142. if ($do_post) {
  143. curl_setopt($ch,CURLOPT_POST,$post_length);
  144. curl_setopt($ch,CURLOPT_POSTFIELDS,$post_query);
  145. }
  146. @curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
  147. @curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
  148. @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,$timeout);
  149. @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  150. @curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  151. @curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  152. if ($ignore_errors) {
  153. @curl_setopt($ch, CURLOPT_FAILONERROR, false);
  154. } else {
  155. @curl_setopt($ch, CURLOPT_FAILONERROR, true);
  156. }
  157. $data = curl_exec($ch);
  158. curl_close($ch);
  159. $url_contents = $data;
  160. }
  161. return $url_contents;
  162. }
  163. /**
  164. * If the function name doesn't describe what this one does well enough then
  165. * seriously: you need to stop reading the comments and not worry about it
  166. *
  167. */public static function autoloadClasses($classname) {
  168. foreach (array('/classes/core/','/classes/seeds/') as $location) {
  169. $file = CASH_PLATFORM_ROOT.$location.$classname.'.php';
  170. if (file_exists($file)) {
  171. // using 'include' instead of 'require_once' because of efficiency
  172. include($file);
  173. }
  174. }
  175. }
  176. /**
  177. * Gets API credentials for the effective or actual user
  178. *
  179. * @param {string} effective || actual
  180. * @return array
  181. */public static function getAPICredentials($user_type='effective') {
  182. $data_request = new CASHRequest(null);
  183. $user_id = $data_request->sessionGet('cash_' . $user_type . '_user');
  184. if ($user_id) {
  185. $data_request = new CASHRequest(
  186. array(
  187. 'cash_request_type' => 'system',
  188. 'cash_action' => 'getapicredentials',
  189. 'user_id' => $user_id
  190. )
  191. );
  192. return $data_request->response['payload'];
  193. }
  194. return false;
  195. }
  196. /**
  197. * Very basic. Takes a URL and checks if headers have been sent. If not we
  198. * do a proper location header redirect. If headers have been sent it
  199. * returns a line of JS to initiate a client-side redirect.
  200. *
  201. * @return none
  202. */public static function redirectToUrl($url) {
  203. if (!headers_sent()) {
  204. header("Location: $url");
  205. exit;
  206. } else {
  207. return '<script type="text/javascript">window.location = "' . $url . '";</script>';
  208. }
  209. }
  210. public static function findReplaceInFile($filename,$find,$replace) {
  211. if (is_file($filename)) {
  212. $file = file_get_contents($filename);
  213. $file = str_replace($find, $replace, $file);
  214. if (file_put_contents($filename, $file)) {
  215. return true;
  216. } else {
  217. return false;
  218. }
  219. } else {
  220. return false;
  221. }
  222. }
  223. public static function getSystemSettings($setting_name='all') {
  224. $cash_settings = parse_ini_file(CASH_PLATFORM_ROOT.'/settings/cashmusic.ini.php');
  225. if ($setting_name == 'all') {
  226. return $cash_settings;
  227. } else {
  228. if (array_key_exists($setting_name, $cash_settings)) {
  229. return $cash_settings[$setting_name];
  230. } else {
  231. return false;
  232. }
  233. }
  234. }
  235. public static function setSystemSetting($setting_name=false,$value='') {
  236. if ($setting_name) {
  237. $cash_settings = parse_ini_file(CASH_PLATFORM_ROOT.'/settings/cashmusic.ini.php');
  238. if (array_key_exists($setting_name, $cash_settings)) {
  239. $success = CASHSystem::findReplaceInFile(
  240. CASH_PLATFORM_ROOT.'/settings/cashmusic.ini.php',
  241. $setting_name . ' = "' . $cash_settings[$setting_name],
  242. $setting_name . ' = "' . $value
  243. );
  244. } else {
  245. return false;
  246. }
  247. } else {
  248. return false;
  249. }
  250. }
  251. public static function getSystemSalt() {
  252. $cash_settings = parse_ini_file(CASH_PLATFORM_ROOT.'/settings/cashmusic.ini.php');
  253. return $cash_settings['salt'];
  254. }
  255. /**
  256. * Super basic XOR encoding — used for encoding connection data
  257. *
  258. */public static function simpleXOR($input, $key = false) {
  259. if (!$key) {
  260. $key = CASHSystem::getSystemSalt();
  261. }
  262. // append key on itself until it is longer than the input
  263. while (strlen($key) < strlen($input)) { $key .= $key; }
  264. // trim key to the length of the input
  265. $key = substr($key, 0, strlen($input));
  266. // Simple XOR'ing, each input byte with each key byte.
  267. $result = '';
  268. for ($i = 0; $i < strlen($input); $i++) {
  269. $result .= $input{$i} ^ $key{$i};
  270. }
  271. return $result;
  272. }
  273. /**
  274. * Formats a proper response, stores it in the session, and returns it
  275. *
  276. * @return array
  277. */public static function getRemoteIP() {
  278. $proxy = '';
  279. if(!defined('STDIN')) {
  280. if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
  281. if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
  282. $proxy = $_SERVER["HTTP_CLIENT_IP"];
  283. } else {
  284. $proxy = $_SERVER["REMOTE_ADDR"];
  285. }
  286. $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
  287. } else {
  288. if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
  289. $ip = $_SERVER["HTTP_CLIENT_IP"];
  290. } else {
  291. $ip = $_SERVER["REMOTE_ADDR"];
  292. }
  293. }
  294. } else {
  295. $ip = 'local';
  296. }
  297. $ip_and_proxy = array(
  298. 'ip' => $ip,
  299. 'proxy' => $proxy
  300. );
  301. return $ip_and_proxy;
  302. }
  303. /**
  304. * Returns the (best guess at) current URL or false for CLI access
  305. *
  306. * @return array
  307. */public static function getCurrentURL($domain_only=false) {
  308. if(!defined('STDIN')) { // check for command line
  309. if ($domain_only) {
  310. return strtok($_SERVER['HTTP_HOST'],':');
  311. } else {
  312. $root = 'http'.((empty($_SERVER['HTTPS'])&&$_SERVER['SERVER_PORT']!=443)?'':'s')
  313. .'://'.$_SERVER['HTTP_HOST'];
  314. $page = strtok($_SERVER['REQUEST_URI'],'?');
  315. return $root.$page;
  316. }
  317. } else {
  318. return false;
  319. }
  320. }
  321. /**
  322. * Takes a datestamp or a string capable of being converted to a datestamp and
  323. * returns a "23 minutes ago" type string for it. Now you can be cute like
  324. * Twitter.
  325. *
  326. * @return string
  327. */public static function formatTimeAgo($time) {
  328. if (is_string($time)) {
  329. $datestamp = strtotime($time);
  330. } else {
  331. $datestamp = $time;
  332. }
  333. $seconds = floor((time() - $datestamp));
  334. if ($seconds < 60) {
  335. $ago_str = $seconds . ' seconds ago';
  336. } else if ($seconds >= 60 && $seconds < 120) {
  337. $ago_str = '1 minute ago';
  338. } else if ($seconds >= 120 && $seconds < 3600) {
  339. $ago_str = floor($seconds / 60) .' minutes ago';
  340. } else if ($seconds >= 3600 && $seconds < 7200) {
  341. $ago_str = '1 hour ago';
  342. } else if ($seconds >= 7200 && $seconds < 86400) {
  343. $ago_str = floor($seconds / 3600) .' hours ago';
  344. } else {
  345. $ago_str = date('d M', $datestamp);
  346. }
  347. return $ago_str;
  348. }
  349. /**
  350. * Turns plain text links into HYPERlinks. Welcome to the future, chump.
  351. *
  352. * Stole all the regex from:
  353. * http://buildinternet.com/2010/05/how-to-automatically-linkify-text-with-php-regular-expressions/
  354. * (Because I stink at regex.)
  355. *
  356. * @return string
  357. */public static function linkifyText($text,$twitter=false) {
  358. $text= preg_replace("/(^|[\n ])([\w]*?)((ht|f)tp(s)?:\/\/[\w]+[^ \,\"\n\r\t<]*)/is", "$1$2<a href=\"$3\">$3</a>", $text);
  359. $text= preg_replace("/(^|[\n ])([\w]*?)((www|ftp)\.[^ \,\"\t\n\r<]*)/is", "$1$2<a href=\"http://$3\">$3</a>", $text);
  360. $text= preg_replace("/(^|[\n ])([a-z0-9&\-_\.]+?)@([\w\-]+\.([\w\-\.]+)+)/i", "$1<a href=\"mailto:$2@$3\">$2@$3</a>", $text);
  361. if ($twitter) {
  362. $text= preg_replace("/@(\w+)/", '<a href="http://www.twitter.com/$1" target="_blank">@$1</a>', $text);
  363. $text= preg_replace("/\#(\w+)/", '<a href="http://search.twitter.com/search?q=$1" target="_blank">#$1</a>',$text);
  364. }
  365. return $text;
  366. }
  367. /*
  368. * Returns the system default email address from the settings ini file
  369. *
  370. * USAGE:
  371. * ASHSystem::getDefaultEmail();
  372. *
  373. */public static function getDefaultEmail() {
  374. $cash_settings = parse_ini_file(CASH_PLATFORM_ROOT.'/settings/cashmusic.ini.php');
  375. return $cash_settings['systememail'];
  376. }
  377. public static function notExplicitFalse($test) {
  378. if ($test === false) {
  379. return false;
  380. } else {
  381. return true;
  382. }
  383. }
  384. public static function getBrowserIdStatus($assertion,$return_details=false) {
  385. if (!$assertion) {
  386. return false;
  387. } else {
  388. $post_data = array(
  389. 'assertion' => $assertion,
  390. 'audience' => CASHSystem::getCurrentURL(true)
  391. );
  392. $status = json_decode(CASHSystem::getURLContents('https://browserid.org/verify',$post_data,true),true);
  393. if ($return_details || !$status) {
  394. return $status;
  395. } else {
  396. if ($status['status'] == 'okay') {
  397. return $status['email'];
  398. } else {
  399. return false;
  400. }
  401. }
  402. }
  403. }
  404. public static function getBrowserIdJS($element_id=false) {
  405. $js_string = '<script src="https://browserid.org/include.js" type="text/javascript">'
  406. . '</script><script type="text/javascript">'
  407. . "(function(){function ha() {navigator.id.get(function(a){if(a){var i = document.getElementById('browseridassertion');if(i){i.value = a;var f=document.getElementById('cash_signin_form');if(f){f.submit();}}}});}var el=document.getElementById('browserid_login_link');if(el.attachEvent){el.attachEvent('onclick',ha);}else{el.addEventListener('click',ha,false);}}());"
  408. . '</script>';
  409. if ($element_id) {
  410. $js_string = str_replace(
  411. array('browseridassertion','browserid_login_link','cash_signin_form'),
  412. array('browseridassertion_'.$element_id,'browserid_login_link_'.$element_id,'cash_signin_form_'.$element_id),
  413. $js_string
  414. );
  415. }
  416. return $js_string;
  417. /*
  418. ORIGINAL un-minified JavaScript:
  419. <script src="https://browserid.org/include.js" type="text/javascript"></script>
  420. <script type="text/javascript">
  421. (function() {
  422. // deal with the return from browserid.org
  423. function handleAssertion() {
  424. navigator.id.get(function(assertion) {
  425. if (assertion) {
  426. var assertioninput = document.getElementById('browseridassertion_106');
  427. if (assertioninput) {
  428. assertioninput.value = assertion;
  429. var loginform = document.getElementById('cash_signin_form_106');
  430. if (loginform) {
  431. loginform.submit();
  432. }
  433. }
  434. }
  435. });
  436. }
  437. // attach elements
  438. var el = document.getElementById('browserid_login_link');
  439. if (el.attachEvent) { // handle IE freakshowfirst — fucking seriously? it's 2012 dudes, get with it
  440. el.attachEvent('onclick',handleAssertion);
  441. } else {
  442. el.addEventListener('click',handleAssertion,false);
  443. }
  444. }());
  445. </script>
  446. */
  447. }
  448. /*
  449. * Sends a plain text and HTML email for system things like email verification,
  450. * password resets, etc.
  451. *
  452. * USAGE:
  453. * CASHSystem::sendEmail('test email','CASH Music <info@cashmusic.org>','dev@cashmusic.org','message, with link: http://cashmusic.org/','title');
  454. *
  455. */public static function sendEmail($subject,$fromaddress,$toaddress,$message_text,$message_title,$encoded_html=false) {
  456. //create a boundary string. It must be unique
  457. //so we use the MD5 algorithm to generate a random hash
  458. $random_hash = md5(date('r', time()));
  459. //define the headers we want passed. Note that they are separated with \r\n
  460. $headers = "From: $fromaddress\r\nReply-To: $fromaddress";
  461. //add boundary string and mime type specification
  462. $headers .= "\r\nContent-Type: multipart/alternative; boundary=\"PHP-alt-".$random_hash."\"";
  463. //define the body of the message.
  464. $message = "--PHP-alt-$random_hash\n";
  465. $message .= "Content-Type: text/plain; charset=\"iso-8859-1\"\n";
  466. $message .= "Content-Transfer-Encoding: 7bit\n\n";
  467. $message .= "$message_title\n\n";
  468. $message .= $message_text;
  469. $message .= "\n--PHP-alt-$random_hash\n";
  470. $message .= "Content-Type: text/html; charset=\"iso-8859-1\"\n";
  471. $message .= "Content-Transfer-Encoding: 7bit\n\n";
  472. if ($encoded_html) {
  473. $message .= $encoded_html;
  474. } else {
  475. $message .= '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>' . $message_title . '</title></head><body>';
  476. $message .= "<style type=\"text/css\">\n";
  477. if (file_exists(CASH_PLATFORM_ROOT.'/settings/defaults/system_email_styles.css')) {
  478. $message .= file_get_contents(CASH_PLATFORM_ROOT.'/settings/defaults/system_email_styles.css');
  479. }
  480. $message .= "</style>\n";
  481. $message .= "<h1>$message_title</h1>\n";
  482. $message .= "<p>";
  483. $message .= str_replace("\n","<br />\n",preg_replace('/(http:\/\/(\S*))/', '<a href="\1">\1</a>', $message_text));
  484. $message .= "</p></body></html>";
  485. }
  486. $message .= "\n--PHP-alt-$random_hash--\n";
  487. //send the email
  488. $mail_sent = @mail($toaddress,$subject,$message,$headers);
  489. return $mail_sent;
  490. }
  491. } // END class
  492. ?>