PageRenderTime 94ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/library/core/functions.general.php

https://github.com/wufoo/Garden
PHP | 1599 lines | 1422 code | 50 blank | 127 comment | 131 complexity | 072cbaaf80a41add7e42bd5367103044 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, BSD-3-Clause, MIT

Large files files are truncated, but you can click here to view the full file

  1. <?php if (!defined('APPLICATION')) exit();
  2. /*
  3. Copyright 2008, 2009 Vanilla Forums Inc.
  4. This file is part of Garden.
  5. Garden is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  6. Garden is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  7. You should have received a copy of the GNU General Public License along with Garden. If not, see <http://www.gnu.org/licenses/>.
  8. Contact Vanilla Forums Inc. at support [at] vanillaforums [dot] com
  9. */
  10. function Gdn_Autoload($ClassName) {
  11. if (!class_exists('Gdn_FileSystem', FALSE))
  12. return false;
  13. if (!class_exists('Gdn_LibraryMap', FALSE))
  14. return false;
  15. if (!class_exists('Gdn', FALSE))
  16. return false;
  17. if (substr($ClassName, 0, 4) === 'Gdn_')
  18. $LibraryFileName = 'class.' . strtolower(substr($ClassName, 4)) . '.php';
  19. else
  20. $LibraryFileName = 'class.' . strtolower($ClassName) . '.php';
  21. if (!is_null($ApplicationManager = Gdn::Factory('ApplicationManager')))
  22. $ApplicationWhiteList = Gdn::Factory('ApplicationManager')->EnabledApplicationFolders();
  23. else
  24. $ApplicationWhiteList = NULL;
  25. $LibraryPath = FALSE;
  26. // If this is a model, look in the models folder(s)
  27. if (strtolower(substr($ClassName, -5)) == 'model')
  28. $LibraryPath = Gdn_FileSystem::FindByMapping('library', PATH_APPLICATIONS, $ApplicationWhiteList, 'models' . DS . $LibraryFileName);
  29. if (Gdn::PluginManager() instanceof Gdn_PluginManager) {
  30. // Look for plugin files.
  31. if ($LibraryPath === FALSE) {
  32. $PluginFolders = Gdn::PluginManager()->EnabledPluginFolders();
  33. $LibraryPath = Gdn_FileSystem::FindByMapping('library', PATH_PLUGINS, $PluginFolders, $LibraryFileName);
  34. }
  35. // Look harder for plugin files.
  36. if ($LibraryPath === FALSE) {
  37. $LibraryPath = Gdn_FileSystem::FindByMapping('plugin', FALSE, FALSE, $ClassName);
  38. }
  39. }
  40. // Look for the class in the applications' library folders.
  41. if ($LibraryPath === FALSE) {
  42. $LibraryPath = Gdn_FileSystem::FindByMapping('library', PATH_APPLICATIONS, $ApplicationWhiteList, "library/$LibraryFileName");
  43. }
  44. // Look for the class in the core.
  45. if ($LibraryPath === FALSE)
  46. $LibraryPath = Gdn_FileSystem::FindByMapping(
  47. 'library',
  48. PATH_LIBRARY,
  49. array(
  50. 'core',
  51. 'database',
  52. 'vendors'. DS . 'phpmailer'
  53. ),
  54. $LibraryFileName
  55. );
  56. // If it still hasn't been found, check for modules
  57. if ($LibraryPath === FALSE)
  58. $LibraryPath = Gdn_FileSystem::FindByMapping('library', PATH_APPLICATIONS, $ApplicationWhiteList, 'modules' . DS . $LibraryFileName);
  59. if ($LibraryPath !== FALSE)
  60. include_once($LibraryPath);
  61. }
  62. if (!function_exists('__autoload')) {
  63. function __autoload($ClassName) {
  64. trigger_error('__autoload() is deprecated. Use sp_autoload_call() instead.', E_USER_DEPRECATED);
  65. spl_autoload_call($ClassName);
  66. }
  67. }
  68. spl_autoload_register('Gdn_Autoload', FALSE);
  69. if (!function_exists('AddActivity')) {
  70. /**
  71. * A convenience function that allows adding to the activity table with a single line.
  72. */
  73. function AddActivity($ActivityUserID, $ActivityType, $Story = '', $RegardingUserID = '', $Route = '', $SendEmail = '') {
  74. $ActivityModel = new ActivityModel();
  75. return $ActivityModel->Add($ActivityUserID, $ActivityType, $Story, $RegardingUserID, '', $Route, $SendEmail);
  76. }
  77. }
  78. if (!function_exists('ArrayCombine')) {
  79. /**
  80. * PHP's array_combine has a limitation that doesn't allow array_combine to
  81. * work if either of the arrays are empty.
  82. */
  83. function ArrayCombine($Array1, $Array2) {
  84. if (!is_array($Array1))
  85. $Array1 = array();
  86. if (!is_array($Array2))
  87. $Array2 = array();
  88. if (count($Array1) > 0 && count($Array2) > 0)
  89. return array_combine($Array1, $Array2);
  90. elseif (count($Array1) == 0)
  91. return $Array2;
  92. else
  93. return $Array1;
  94. }
  95. }
  96. /*
  97. We now support PHP 5.2.0 - Which should make this declaration unnecessary.
  98. if (!function_exists('array_fill_keys')) {
  99. function array_fill_keys($Keys, $Val) {
  100. return array_combine($Keys,array_fill(0,count($Keys),$Val));
  101. }
  102. }
  103. */
  104. if (!function_exists('ArrayHasValue')) {
  105. /**
  106. * Searches $Array (and all arrays it contains) for $Value.
  107. */
  108. function ArrayHasValue($Array, $Value) {
  109. if (in_array($Value, $Array)) {
  110. return TRUE;
  111. } else {
  112. foreach ($Array as $k => $v) {
  113. if (is_array($v) && ArrayHasValue($v, $Value) === TRUE) return TRUE;
  114. }
  115. return FALSE;
  116. }
  117. }
  118. }
  119. if (!function_exists('ArrayKeyExistsI')) {
  120. /**
  121. * Case-insensitive ArrayKeyExists search.
  122. */
  123. function ArrayKeyExistsI($Key, $Search) {
  124. if (is_array($Search)) {
  125. foreach ($Search as $k => $v) {
  126. if (strtolower($Key) == strtolower($k))
  127. return TRUE;
  128. }
  129. }
  130. return FALSE;
  131. }
  132. }
  133. if (!function_exists('ArrayInArray')) {
  134. /**
  135. * Searches Haystack array for items in Needle array. If FullMatch is TRUE,
  136. * all items in Needle must also be in Haystack. If FullMatch is FALSE, only
  137. * one-or-more items in Needle must be in Haystack.
  138. *
  139. * @param array $Needle The array containing items to match to Haystack.
  140. * @param array $Haystack The array to search in for Needle items.
  141. * @param bool $FullMatch Should all items in Needle be found in Haystack to return TRUE?
  142. */
  143. function ArrayInArray($Needle, $Haystack, $FullMatch = TRUE) {
  144. $Count = count($Needle);
  145. $Return = $FullMatch ? TRUE : FALSE;
  146. for ($i = 0; $i < $Count; ++$i) {
  147. if ($FullMatch === TRUE) {
  148. if (in_array($Needle[$i], $Haystack) === FALSE)
  149. $Return = FALSE;
  150. } else {
  151. if (in_array($Needle[$i], $Haystack) === TRUE) {
  152. $Return = TRUE;
  153. break;
  154. }
  155. }
  156. }
  157. return $Return;
  158. }
  159. }
  160. if (!function_exists('ArrayTranslate')) {
  161. /**
  162. * Take all of the items specified in an array and make a new array with them specified by mappings.
  163. *
  164. *
  165. * @param array $Array The input array to translate.
  166. * @param array $Mappings The mappings to translate the array.
  167. * @return array
  168. */
  169. function ArrayTranslate($Array, $Mappings) {
  170. $Result = array();
  171. foreach ($Mappings as $Index => $Value) {
  172. if (is_numeric($Index)) {
  173. $Key = $Value;
  174. $NewKey = $Value;
  175. } else {
  176. $Key = $Index;
  177. $NewKey = $Value;
  178. }
  179. if (isset($Array[$Key]))
  180. $Result[$NewKey] = $Array[$Key];
  181. else
  182. $Result[$NewKey] = NULL;
  183. }
  184. return $Result;
  185. }
  186. }
  187. if (!function_exists('ArrayValue')) {
  188. /**
  189. * Returns the value associated with the $Needle key in the $Haystack
  190. * associative array or FALSE if not found. This is a CASE-SENSITIVE search.
  191. *
  192. * @param string The key to look for in the $Haystack associative array.
  193. * @param array The associative array in which to search for the $Needle key.
  194. * @param string The default value to return if the requested value is not found. Default is FALSE.
  195. */
  196. function ArrayValue($Needle, $Haystack, $Default = FALSE) {
  197. $Result = GetValue($Needle, $Haystack, $Default);
  198. return $Result;
  199. }
  200. }
  201. if (!function_exists('ArrayValueI')) {
  202. /**
  203. * Returns the value associated with the $Needle key in the $Haystack
  204. * associative array or FALSE if not found. This is a CASE-INSENSITIVE
  205. * search.
  206. *
  207. * @param string The key to look for in the $Haystack associative array.
  208. * @param array The associative array in which to search for the $Needle key.
  209. * @param string The default value to return if the requested value is not found. Default is FALSE.
  210. */
  211. function ArrayValueI($Needle, $Haystack, $Default = FALSE) {
  212. $Return = $Default;
  213. if (is_array($Haystack)) {
  214. foreach ($Haystack as $Key => $Value) {
  215. if (strtolower($Needle) == strtolower($Key)) {
  216. $Return = $Value;
  217. break;
  218. }
  219. }
  220. }
  221. return $Return;
  222. }
  223. }
  224. if (!function_exists('ArrayValuesToKeys')) {
  225. /** Takes an array's values and applies them to a new array as both the keys
  226. * and values.
  227. */
  228. function ArrayValuesToKeys($Array) {
  229. return array_combine(array_values($Array), $Array);
  230. }
  231. }
  232. if (!function_exists('Asset')) {
  233. /**
  234. * Takes the path to an asset (image, js file, css file, etc) and prepends the webroot.
  235. */
  236. function Asset($Destination = '', $WithDomain = FALSE, $AddVersion = FALSE) {
  237. $Destination = str_replace('\\', '/', $Destination);
  238. if (substr($Destination, 0, 7) == 'http://') {
  239. $Result = $Destination;
  240. } else {
  241. $Parts = array(Gdn_Url::WebRoot($WithDomain), $Destination);
  242. if (!$WithDomain)
  243. array_unshift($Parts, '/');
  244. $Result = CombinePaths($Parts, '/');
  245. }
  246. if ($AddVersion) {
  247. if (strpos($Result, '?') === FALSE)
  248. $Result .= '?';
  249. else
  250. $Result .= '&';
  251. $Result.= 'v='.urlencode(APPLICATION_VERSION);
  252. }
  253. return $Result;
  254. }
  255. }
  256. if (!function_exists('Attribute')) {
  257. /**
  258. * Takes an attribute (or array of attributes) and formats them in
  259. * attribute="value" format.
  260. */
  261. function Attribute($Name, $Value = '') {
  262. $Return = '';
  263. if (!is_array($Name)) {
  264. $Name = array($Name => $Value);
  265. }
  266. foreach ($Name as $Attribute => $Val) {
  267. if ($Val != '') {
  268. $Return .= ' '.$Attribute.'="'.$Val.'"';
  269. }
  270. }
  271. return $Return;
  272. }
  273. }
  274. if (!function_exists('C')) {
  275. /**
  276. * Retrieves a configuration setting.
  277. * @param string $Name The name of the configuration setting. Settings in different sections are seperated by a dot ('.')
  278. * @param mixed $Default The result to return if the configuration setting is not found.
  279. * @return mixed The configuration setting.
  280. * @see Gdn::Config()
  281. */
  282. function C($Name = FALSE, $Default = FALSE) {
  283. return Gdn::Config($Name, $Default);
  284. }
  285. }
  286. if (!function_exists('CalculateNumberOfPages')) {
  287. /**
  288. * Based on the total number of items and the number of items per page,
  289. * this function will calculate how many pages there are.
  290. * Returns the number of pages available
  291. */
  292. function CalculateNumberOfPages($ItemCount, $ItemsPerPage) {
  293. $TmpCount = ($ItemCount/$ItemsPerPage);
  294. $RoundedCount = intval($TmpCount);
  295. $PageCount = 0;
  296. if ($TmpCount > 1) {
  297. if ($TmpCount > $RoundedCount) {
  298. $PageCount = $RoundedCount + 1;
  299. } else {
  300. $PageCount = $RoundedCount;
  301. }
  302. } else {
  303. $PageCount = 1;
  304. }
  305. return $PageCount;
  306. }
  307. }
  308. if (!function_exists('ChangeBasename')) {
  309. /** Change the basename part of a filename for a given path.
  310. *
  311. * @param string $Path The path to alter.
  312. * @param string $NewBasename The new basename. A %s will be replaced by the old basename.
  313. * @return string
  314. */
  315. function ChangeBasename($Path, $NewBasename) {
  316. $NewBasename = str_replace('%s', '$2', $NewBasename);
  317. $Result = preg_replace('/^(.*\/)?(.*?)(\.[^.]+)$/', '$1'.$NewBasename.'$3', $Path);
  318. return $Result;
  319. }
  320. }
  321. if (!function_exists('CheckPermission')) {
  322. function CheckPermission($PermissionName) {
  323. $Result = Gdn::Session()->CheckPermission($PermissionName);
  324. return $Result;
  325. }
  326. }
  327. if (!function_exists('CheckRequirements')) {
  328. function CheckRequirements($ItemName, $RequiredItems, $EnabledItems, $RequiredItemTypeCode) {
  329. // 1. Make sure that $RequiredItems are present
  330. if (is_array($RequiredItems)) {
  331. $MissingRequirements = array();
  332. foreach ($RequiredItems as $RequiredItemName => $RequiredVersion) {
  333. if (!array_key_exists($RequiredItemName, $EnabledItems)) {
  334. $MissingRequirements[] = "$RequiredItemName $RequiredVersion";
  335. } else if ($RequiredVersion && $RequiredVersion != '*') { // * means any version
  336. $EnabledItems;
  337. // If the item exists and is enabled, check the version
  338. $EnabledVersion = ArrayValue('Version', ArrayValue($RequiredItemName, $EnabledItems, array()), '');
  339. // Compare the versions.
  340. if (version_compare($EnabledVersion, $RequiredVersion, '<')) {
  341. $MissingRequirements[] = "$RequiredItemName $RequiredVersion";
  342. }
  343. }
  344. }
  345. if (count($MissingRequirements) > 0) {
  346. $Msg = sprintf("%s is missing the following requirement(s): %s.",
  347. $ItemName,
  348. implode(', ', $MissingRequirements));
  349. throw new Gdn_UserException($Msg);
  350. }
  351. }
  352. }
  353. }
  354. if (!function_exists('check_utf8')){
  355. function check_utf8($str) {
  356. $len = strlen($str);
  357. for($i = 0; $i < $len; $i++){
  358. $c = ord($str[$i]);
  359. if ($c > 128) {
  360. if (($c > 247)) return false;
  361. elseif ($c > 239) $bytes = 4;
  362. elseif ($c > 223) $bytes = 3;
  363. elseif ($c > 191) $bytes = 2;
  364. else return false;
  365. if (($i + $bytes) > $len) return false;
  366. while ($bytes > 1) {
  367. $i++;
  368. $b = ord($str[$i]);
  369. if ($b < 128 || $b > 191) return false;
  370. $bytes--;
  371. }
  372. }
  373. }
  374. return true;
  375. }
  376. }
  377. if (!function_exists('CombinePaths')) {
  378. // filesystem input/output functions that deal with loading libraries, application paths, etc.
  379. function CombinePaths($Paths, $Delimiter = DS) {
  380. if (is_array($Paths)) {
  381. $MungedPath = implode($Delimiter, $Paths);
  382. $MungedPath = str_replace(array($Delimiter.$Delimiter.$Delimiter, $Delimiter.$Delimiter), array($Delimiter, $Delimiter), $MungedPath);
  383. return str_replace(array('http:/', 'https:/'), array('http://', 'https://'), $MungedPath);
  384. } else {
  385. return $Paths;
  386. }
  387. }
  388. }
  389. if (!function_exists('ConcatSep')) {
  390. /** Concatenate a string to another string with a seperator.
  391. *
  392. * @param string $Sep The seperator string to use between the concatenated strings.
  393. * @param string $Str1 The first string in the concatenation chain.
  394. * @param mixed $Str2 The second string in the concatenation chain.
  395. * - This parameter can be an array in which case all of its elements will be concatenated.
  396. * - If this parameter is a string then the function will look for more arguments to concatenate.
  397. * @return string
  398. */
  399. function ConcatSep($Sep, $Str1, $Str2) {
  400. if(is_array($Str2)) {
  401. $Strings = array_merge((array)$Str1, $Str2);
  402. } else {
  403. $Strings = func_get_args();
  404. array_shift($Strings);
  405. }
  406. $Result = '';
  407. foreach($Strings as $String) {
  408. if(!$String)
  409. continue;
  410. if($Result)
  411. $Result .= $Sep;
  412. $Result .= $String;
  413. }
  414. return $Result;
  415. }
  416. }
  417. if (!function_exists('ConsolidateArrayValuesByKey')) {
  418. /**
  419. * Takes an array of associative arrays (ie. a dataset array), a $Key, and
  420. * merges all of the values for that key into a single array, returning it.
  421. */
  422. function ConsolidateArrayValuesByKey($Array, $Key, $ValueKey = '', $DefaultValue = NULL) {
  423. $Return = array();
  424. foreach ($Array as $Index => $AssociativeArray) {
  425. if(is_object($AssociativeArray)) {
  426. if($ValueKey === '') {
  427. $Return[] = $AssociativeArray->$Key;
  428. } elseif(property_exists($AssociativeArray, $ValueKey)) {
  429. $Return[$AssociativeArray[$Key]] = $AssociativeArray->$ValueKey;
  430. } else {
  431. $Return[$AssociativeArray->$Key] = $DefaultValue;
  432. }
  433. } elseif (array_key_exists($Key, $AssociativeArray)) {
  434. if($ValueKey === '') {
  435. $Return[] = $AssociativeArray[$Key];
  436. } elseif (array_key_exists($ValueKey, $AssociativeArray)) {
  437. $Return[$AssociativeArray[$Key]] = $AssociativeArray[$ValueKey];
  438. } else {
  439. $Return[$AssociativeArray[$Key]] = $DefaultValue;
  440. }
  441. }
  442. }
  443. return $Return;
  444. }
  445. }
  446. if (!function_exists('decho')) {
  447. /**
  448. * Echo's debug variables if user is root admin.
  449. */
  450. function decho($Mixed, $Prefix = 'DEBUG: ') {
  451. if (Gdn::Session()->CheckPermission('Garden.Debug.Allow')) {
  452. echo '<div>'.$Prefix;
  453. if (is_string($Mixed))
  454. echo $Mixed;
  455. else
  456. var_dump($Mixed);
  457. echo '</div>';
  458. }
  459. }
  460. }
  461. if (!function_exists('filter_input')) {
  462. if (!defined('INPUT_GET')) define('INPUT_GET', 'INPUT_GET');
  463. if (!defined('INPUT_POST')) define('INPUT_POST', 'INPUT_POST');
  464. if (!defined('FILTER_SANITIZE_STRING')) define('FILTER_SANITIZE_STRING', 'FILTER_SANITIZE_STRING');
  465. if (!defined('FILTER_REQUIRE_ARRAY')) define('FILTER_REQUIRE_ARRAY', 'FILTER_REQUIRE_ARRAY');
  466. function filter_input($InputType, $FieldName, $Filter = '', $Options = '') {
  467. $Collection = $InputType == INPUT_GET ? $_GET : $_POST;
  468. $Value = ArrayValue($FieldName, $Collection, '');
  469. if (get_magic_quotes_gpc()) {
  470. if (is_array($Value)) {
  471. $Count = count($Value);
  472. for ($i = 0; $i < $Count; ++$i) {
  473. $Value[$i] = stripslashes($Value[$i]);
  474. }
  475. } else {
  476. $Value = stripslashes($Value);
  477. }
  478. }
  479. return $Value;
  480. }
  481. }
  482. if (!function_exists('ForceBool')) {
  483. function ForceBool($Value, $DefaultValue = FALSE, $True = TRUE, $False = FALSE) {
  484. if (is_bool($Value)) {
  485. return $Value ? $True : $False;
  486. } else if (is_numeric($Value)) {
  487. return $Value == 0 ? $False : $True;
  488. } else if (is_string($Value)) {
  489. return strtolower($Value) == 'true' ? $True : $False;
  490. } else {
  491. return $DefaultValue;
  492. }
  493. }
  494. }
  495. if (!function_exists('ForceSSL')) {
  496. /**
  497. * Checks the current url for SSL and redirects to SSL version if not
  498. * currently on it. Call at the beginning of any method you want forced to
  499. * be in SSL. Garden.AllowSSL must be TRUE in order for this function to
  500. * work.
  501. */
  502. function ForceSSL() {
  503. if (C('Garden.AllowSSL')) {
  504. if (Gdn::Request()->Scheme() != 'https')
  505. Redirect(Gdn::Request()->Url('', TRUE, TRUE));
  506. }
  507. }
  508. }
  509. // Formats values to be saved as PHP arrays.
  510. if (!function_exists('FormatArrayAssignment')) {
  511. function FormatArrayAssignment(&$Array, $Prefix, $Value) {
  512. if (is_array($Value)) {
  513. // If $Value doesn't contain a key of "0" OR it does and it's value IS
  514. // an array, this should be treated as an associative array.
  515. $IsAssociativeArray = array_key_exists(0, $Value) === FALSE || is_array($Value[0]) === TRUE ? TRUE : FALSE;
  516. if ($IsAssociativeArray === TRUE) {
  517. foreach ($Value as $k => $v) {
  518. FormatArrayAssignment($Array, $Prefix."['$k']", $v);
  519. }
  520. } else {
  521. // If $Value is not an associative array, just write it like a simple array definition.
  522. $FormattedValue = array_map(array('Gdn_Format', 'ArrayValueForPhp'), $Value);
  523. $Array[] = $Prefix .= " = array('".implode("', '", $FormattedValue)."');";
  524. }
  525. } elseif (is_int($Value)) {
  526. $Array[] = $Prefix .= ' = '.$Value.';';
  527. } elseif (is_bool($Value)) {
  528. $Array[] = $Prefix .= ' = '.($Value ? 'TRUE' : 'FALSE').';';
  529. } elseif (in_array($Value, array('TRUE', 'FALSE'))) {
  530. $Array[] = $Prefix .= ' = '.($Value == 'TRUE' ? 'TRUE' : 'FALSE').';';
  531. } else {
  532. if (strpos($Value, "'") !== FALSE) {
  533. $Array[] = $Prefix .= ' = "'.Gdn_Format::ArrayValueForPhp(str_replace('"', '\"', $Value)).'";';
  534. } else {
  535. $Array[] = $Prefix .= " = '".Gdn_Format::ArrayValueForPhp($Value)."';";
  536. }
  537. }
  538. }
  539. }
  540. if (!function_exists('getallheaders')) {
  541. /**
  542. * If PHP isn't running as an apache module, getallheaders doesn't exist in
  543. * some systems.
  544. * Ref: http://github.com/lussumo/Garden/issues/closed#issue/3/comment/19938
  545. */
  546. function getallheaders() {
  547. foreach($_SERVER as $name => $value)
  548. if(substr($name, 0, 5) == 'HTTP_')
  549. $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
  550. return $headers;
  551. }
  552. }
  553. if (!function_exists('GetConnectionString')) {
  554. function GetConnectionString($DatabaseName, $HostName = 'localhost', $ServerType = 'mysql') {
  555. $HostName = explode(':', $HostName);
  556. $Port = count($HostName) == 2 ? $HostName[1] : '';
  557. $HostName = $HostName[0];
  558. $String = $ServerType.':host='.$HostName;
  559. if ($Port != '')
  560. $String .= ';port='.$Port;
  561. return $String .= ';dbname='.$DatabaseName;
  562. }
  563. }
  564. if (!function_exists('GetIncomingValue')) {
  565. /**
  566. * Grabs $FieldName from either the GET or POST collections (whichever one it
  567. * is present in. Checks $_POST first).
  568. */
  569. function GetIncomingValue($FieldName, $Default = FALSE) {
  570. if (array_key_exists($FieldName, $_POST) === TRUE) {
  571. $Result = filter_input(INPUT_POST, $FieldName, FILTER_SANITIZE_STRING); //FILTER_REQUIRE_ARRAY);
  572. } else if (array_key_exists($FieldName, $_GET) === TRUE) {
  573. $Result = filter_input(INPUT_GET, $FieldName, FILTER_SANITIZE_STRING); //, FILTER_REQUIRE_ARRAY);
  574. } else {
  575. $Result = $Default;
  576. }
  577. return $Result;
  578. }
  579. }
  580. if (!function_exists('GetMentions')) {
  581. function GetMentions($String) {
  582. $Mentions = array();
  583. // This one grabs mentions that start at the beginning of $String
  584. preg_match_all(
  585. '/(?:^|[\s,\.])@(\w{3,20})\b/i',
  586. $String,
  587. $Matches
  588. );
  589. if (count($Matches) > 1) {
  590. $Result = array_unique($Matches[1]);
  591. return $Result;
  592. }
  593. return array();
  594. }
  595. }
  596. if (!function_exists('GetObject')) {
  597. /**
  598. * Get a value off of an object.
  599. *
  600. * @deprecated GetObject() is deprecated. Use GetValue() instead.
  601. * @param string $Property The name of the property on the object.
  602. * @param object $Object The object that contains the value.
  603. * @param mixed $Default The default to return if the object doesn't contain the property.
  604. * @return mixed
  605. */
  606. function GetObject($Property, $Object, $Default) {
  607. trigger_error('GetObject() is deprecated. Use GetValue() instead.', E_USER_DEPRECATED);
  608. $Result = GetValue($Property, $Object, $Default);
  609. return $Result;
  610. }
  611. }
  612. if (!function_exists('GetPostValue')) {
  613. /**
  614. * Return the value for $FieldName from the $_POST collection.
  615. */
  616. function GetPostValue($FieldName, $Default = FALSE) {
  617. return array_key_exists($FieldName, $_POST) ? $_POST[$FieldName] : $Default;
  618. }
  619. }
  620. if (!function_exists('GetValue')) {
  621. /**
  622. * Return the value from an associative array or an object.
  623. *
  624. * @param string $Key The key or property name of the value.
  625. * @param mixed $Collection The array or object to search.
  626. * @param mixed $Default The value to return if the key does not exist.
  627. * @param bool $Remove Whether or not to remove the item from the collection.
  628. * @return mixed The value from the array or object.
  629. */
  630. function GetValue($Key, &$Collection, $Default = FALSE, $Remove = FALSE) {
  631. $Result = $Default;
  632. if(is_array($Collection) && array_key_exists($Key, $Collection)) {
  633. $Result = $Collection[$Key];
  634. if($Remove)
  635. unset($Collection[$Key]);
  636. } elseif(is_object($Collection) && property_exists($Collection, $Key)) {
  637. $Result = $Collection->$Key;
  638. if($Remove)
  639. unset($Collection->$Key);
  640. }
  641. return $Result;
  642. }
  643. }
  644. if (!function_exists('GetValueR')) {
  645. /**
  646. * Return the value from an associative array or an object.
  647. * This function differs from GetValue() in that $Key can be a string consisting of dot notation that will be used to recursivly traverse the collection.
  648. *
  649. * @param string $Key The key or property name of the value.
  650. * @param mixed $Collection The array or object to search.
  651. * @param mixed $Default The value to return if the key does not exist.
  652. * @return mixed The value from the array or object.
  653. */
  654. function GetValueR($Key, &$Collection, $Default = FALSE) {
  655. $Path = explode('.', $Key);
  656. $Value = $Collection;
  657. for($i = 0; $i < count($Path); ++$i) {
  658. $SubKey = $Path[$i];
  659. if(is_array($Value) && isset($Value[$SubKey])) {
  660. $Value = $Value[$SubKey];
  661. } elseif(is_object($Value) && isset($Value->$SubKey)) {
  662. $Value = $Value->$SubKey;
  663. } else {
  664. return $Default;
  665. }
  666. }
  667. return $Value;
  668. }
  669. }
  670. if (!function_exists('ImplodeAssoc')) {
  671. /**
  672. * A version of implode() that operates on array keys and values.
  673. *
  674. * @param string $KeyGlue The glue between keys and values.
  675. * @param string $ElementGlue The glue between array elements.
  676. * @param array $Array The array to implode.
  677. * @return string The imploded array.
  678. */
  679. function ImplodeAssoc($KeyGlue, $ElementGlue, $Array) {
  680. $Result = '';
  681. foreach ($Array as $Key => $Value) {
  682. if (strlen($Result) > 0)
  683. $Result .= $ElementGlue;
  684. $Result .= $Key.$KeyGlue.$Value;
  685. }
  686. return $Result;
  687. }
  688. }
  689. if (!function_exists('InArrayI')) {
  690. /**
  691. * Case-insensitive version of php's native in_array function.
  692. */
  693. function InArrayI($Needle, $Haystack) {
  694. $Needle = strtolower($Needle);
  695. foreach ($Haystack as $Item) {
  696. if (strtolower($Item) == $Needle)
  697. return TRUE;
  698. }
  699. return FALSE;
  700. }
  701. }
  702. if (!function_exists('IsMobile')) {
  703. function IsMobile() {
  704. $Mobile = 0;
  705. $AllHttp = strtolower(GetValue('ALL_HTTP', $_SERVER));
  706. $HttpAccept = strtolower(GetValue('HTTP_ACCEPT', $_SERVER));
  707. $UserAgent = strtolower(GetValue('HTTP_USER_AGENT', $_SERVER));
  708. if (preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|opera m)/i', $UserAgent))
  709. $Mobile++;
  710. if(
  711. (strpos($HttpAccept,'application/vnd.wap.xhtml+xml') > 0)
  712. || (
  713. (isset($_SERVER['HTTP_X_WAP_PROFILE'])
  714. || isset($_SERVER['HTTP_PROFILE'])))
  715. )
  716. $Mobile++;
  717. $MobileUserAgent = substr($UserAgent, 0, 4);
  718. $MobileUserAgents = array(
  719. 'w3c ','acs-','alav','alca','amoi','audi','avan','benq','bird','blac',
  720. 'blaz','brew','cell','cldc','cmd-','dang','doco','eric','hipt','inno',
  721. 'ipaq','java','jigs','kddi','keji','leno','lg-c','lg-d','lg-g','lge-',
  722. 'maui','maxo','midp','mits','mmef','mobi','mot-','moto','mwbp','nec-',
  723. 'newt','noki','palm','pana','pant','phil','play','port','prox','qwap',
  724. 'sage','sams','sany','sch-','sec-','send','seri','sgh-','shar','sie-',
  725. 'siem','smal','smar','sony','sph-','symb','t-mo','teli','tim-','tosh',
  726. 'tsm-','upg1','upsi','vk-v','voda','wap-','wapa','wapi','wapp','wapr',
  727. 'webc','winw','winw','xda','xda-');
  728. if (in_array($MobileUserAgent, $MobileUserAgents))
  729. $Mobile++;
  730. if (strpos($AllHttp, 'operamini') > 0)
  731. $Mobile++;
  732. // Windows Mobile 7 contains "windows" in the useragent string, so must comment this out
  733. // if (strpos($UserAgent, 'windows') > 0)
  734. // $Mobile = 0;
  735. return $Mobile > 0;
  736. }
  737. }
  738. if (!function_exists('IsSearchEngine')) {
  739. function IsSearchEngine() {
  740. $Engines = array(
  741. 'googlebot',
  742. 'slurp',
  743. 'search.msn.com',
  744. 'nutch',
  745. 'simpy',
  746. 'bot',
  747. 'aspseek',
  748. 'crawler',
  749. 'msnbot',
  750. 'libwww-perl',
  751. 'fast',
  752. 'baidu',
  753. );
  754. $HttpUserAgent = strtolower(GetValue('HTTP_USER_AGENT', $_SERVER, ''));
  755. if ($HttpUserAgent != '') {
  756. foreach ($Engines as $Engine) {
  757. if (strpos($HttpUserAgent, $Engine) !== FALSE)
  758. return TRUE;
  759. }
  760. }
  761. return FALSE;
  762. }
  763. }
  764. if (!function_exists('IsTimestamp')) {
  765. function IsTimestamp($Stamp) {
  766. return checkdate(
  767. @date("m", $Stamp),
  768. @date("d", $Stamp),
  769. @date("Y", $Stamp)
  770. );
  771. }
  772. }
  773. if (!function_exists('IsWritable')) {
  774. /**
  775. * PHP's native is_writable() function fails to correctly determine write
  776. * capabilities on some systems (Windows), and in our tests it returned TRUE
  777. * despite not being able to create subfolders within the folder being
  778. * checked. Our version truly verifies permissions by performing file-write
  779. * tests.
  780. */
  781. function IsWritable($Path) {
  782. if ($Path{strlen($Path) - 1} == DS) {
  783. // Recursively return a temporary file path
  784. return IsWritable($Path . uniqid(mt_rand()) . '.tmp');
  785. } elseif (is_dir($Path)) {
  786. return IsWritable($Path . '/' . uniqid(mt_rand()) . '.tmp');
  787. }
  788. // Check tmp file for read/write capabilities
  789. $KeepPath = file_exists($Path);
  790. $File = @fopen($Path, 'a');
  791. if ($File === FALSE)
  792. return FALSE;
  793. fclose($File);
  794. if (!$KeepPath)
  795. unlink($Path);
  796. return TRUE;
  797. }
  798. }
  799. if (!function_exists('MergeArrays')) {
  800. /**
  801. * Merge two associative arrays into a single array.
  802. *
  803. * @param array The "dominant" array, who's values will be chosen over those of the subservient.
  804. * @param array The "subservient" array, who's values will be disregarded over those of the dominant.
  805. */
  806. function MergeArrays(&$Dominant, $Subservient) {
  807. foreach ($Subservient as $Key => $Value) {
  808. if (!array_key_exists($Key, $Dominant)) {
  809. // Add the key from the subservient array if it doesn't exist in the
  810. // dominant array.
  811. $Dominant[$Key] = $Value;
  812. } else {
  813. // If the key already exists in the dominant array, only continue if
  814. // both values are also arrays - because we don't want to overwrite
  815. // values in the dominant array with ones from the subservient array.
  816. if (is_array($Dominant[$Key]) && is_array($Value)) {
  817. $Dominant[$Key] = MergeArrays($Dominant[$Key], $Value);
  818. }
  819. }
  820. }
  821. return $Dominant;
  822. }
  823. }
  824. if (!function_exists('Now')) {
  825. function Now() {
  826. list($usec, $sec) = explode(" ", microtime());
  827. return ((float)$usec + (float)$sec);
  828. }
  829. }
  830. if (!function_exists('OffsetLimit')) {
  831. /** Convert various forms of querystring limit/offset, page, limit/range to database limit/offset
  832. *
  833. * @param string $OffsetOrPage The page query in one of the following formats:
  834. * - p<x>: Get page x.
  835. * - <x>-<y>: This is a range viewing records x through y.
  836. * - <x>lim<n>: This is a limit/offset pair.
  837. * - <x>: This is a limit where offset is given in the next parameter.
  838. * @param int $LimitOrPageSize The page size or limit.
  839. */
  840. function OffsetLimit($OffsetOrPage = '', $LimitOrPageSize = '') {
  841. $LimitOrPageSize = is_numeric($LimitOrPageSize) ? $LimitOrPageSize : 50;
  842. if (is_numeric($OffsetOrPage)) {
  843. $Offset = $OffsetOrPage;
  844. $Limit = $LimitOrPageSize;
  845. } elseif (preg_match('/p(\d+)/i', $OffsetOrPage, $Matches)) {
  846. $Page = $Matches[1];
  847. $Offset = $LimitOrPageSize * ($Page - 1);
  848. $Limit = $LimitOrPageSize;
  849. } elseif (preg_match('/(\d+)-(\d+)/', $OffsetOrPage, $Matches)) {
  850. $Offset = $Matches[1] - 1;
  851. $Limit = $Matches[2] - $Matches[1] + 1;
  852. } elseif (preg_match('/(\d+)lim(\d*)/i', $OffsetOrPage, $Matches)) {
  853. $Offset = $Matches[1];
  854. $Limit = $Matches[2];
  855. if (!is_numeric($Limit))
  856. $Limit = $LimitOrPageSize;
  857. } else {
  858. $Offset = 0;
  859. $Limit = $LimitOrPageSize;
  860. }
  861. if ($Offset < 0)
  862. $Offset = 0;
  863. if ($Limit < 0)
  864. $Limit = 50;
  865. return array($Offset, $Limit);
  866. }
  867. }
  868. if (!function_exists('PageNumber')) {
  869. /** Get the page number from a database offset and limit.
  870. *
  871. * @param int $Offset The database offset, starting at zero.
  872. * @param int $Limit The database limit, otherwise known as the page size.
  873. * @param bool $UrlParam Whether or not the result should be formatted as a url parameter, suitable for OffsetLimit.
  874. */
  875. function PageNumber($Offset, $Limit, $UrlParam = FALSE) {
  876. $Result = floor($Offset / $Limit) + 1;
  877. if ($UrlParam)
  878. $Result = 'p'.$Result;
  879. return $Result;
  880. }
  881. }
  882. if (!function_exists('parse_ini_string')) {
  883. /**
  884. * parse_ini_string not supported until PHP 5.3.0, and we currently support
  885. * PHP 5.2.0.
  886. */
  887. function parse_ini_string ($Ini) {
  888. $Lines = split("\n", $Ini);
  889. $Result = array();
  890. foreach($Lines as $Line) {
  891. $Parts = split('=', $Line, 2);
  892. if(count($Parts) == 1) {
  893. $Result[trim($Parts[0])] = '';
  894. } elseif(count($Parts) >= 2) {
  895. $Result[trim($Parts[0])] = trim($Parts[1]);
  896. }
  897. }
  898. return $Result;
  899. }
  900. }
  901. if (!function_exists('PrefixString')) {
  902. /**
  903. * Takes a string, and prefixes it with $Prefix unless it is already prefixed that way.
  904. *
  905. * @param string $Prefix The prefix to use.
  906. * @param string $String The string to be prefixed.
  907. */
  908. function PrefixString($Prefix, $String) {
  909. if (substr($String, 0, strlen($Prefix)) != $Prefix) {
  910. $String = $Prefix . $String;
  911. }
  912. return $String;
  913. }
  914. }
  915. if (!function_exists('ProxyHead')) {
  916. function ProxyHead($Url, $Headers=NULL, $Timeout = FALSE, $FollowRedirects = FALSE) {
  917. if (is_null($Headers))
  918. $Headers = array();
  919. $OriginalHeaders = $Headers;
  920. $OriginalTimeout = $Timeout;
  921. if(!$Timeout)
  922. $Timeout = C('Garden.SocketTimeout', 1.0);
  923. $UrlParts = parse_url($Url);
  924. $Scheme = GetValue('scheme', $UrlParts, 'http');
  925. $Host = GetValue('host', $UrlParts, '');
  926. $Port = GetValue('port', $UrlParts, '80');
  927. $Path = GetValue('path', $UrlParts, '');
  928. $Query = GetValue('query', $UrlParts, '');
  929. // Get the cookie.
  930. $Cookie = '';
  931. $EncodeCookies = C('Garden.Cookie.Urlencode',TRUE);
  932. foreach($_COOKIE as $Key => $Value) {
  933. if(strncasecmp($Key, 'XDEBUG', 6) == 0)
  934. continue;
  935. if(strlen($Cookie) > 0)
  936. $Cookie .= '; ';
  937. $EValue = ($EncodeCookies) ? urlencode($Value) : $Value;
  938. $Cookie .= "{$Key}={$EValue}";
  939. }
  940. $Cookie = array('Cookie' => $Cookie);
  941. $Response = '';
  942. if (function_exists('curl_init')) {
  943. //$Url = $Scheme.'://'.$Host.$Path;
  944. $Handler = curl_init();
  945. curl_setopt($Handler, CURLOPT_TIMEOUT, $Timeout);
  946. curl_setopt($Handler, CURLOPT_URL, $Url);
  947. curl_setopt($Handler, CURLOPT_PORT, $Port);
  948. curl_setopt($Handler, CURLOPT_HEADER, 1);
  949. curl_setopt($Handler, CURLOPT_NOBODY, 1);
  950. curl_setopt($Handler, CURLOPT_USERAGENT, ArrayValue('HTTP_USER_AGENT', $_SERVER, 'Vanilla/2.0'));
  951. curl_setopt($Handler, CURLOPT_RETURNTRANSFER, 1);
  952. curl_setopt($Handler, CURLOPT_HTTPHEADER, $Headers);
  953. if (strlen($Cookie['Cookie']))
  954. curl_setopt($Handler, CURLOPT_COOKIE, $Cookie['Cookie']);
  955. //if ($Query != '') {
  956. // curl_setopt($Handler, CURLOPT_POST, 1);
  957. // curl_setopt($Handler, CURLOPT_POSTFIELDS, $Query);
  958. //}
  959. $Response = curl_exec($Handler);
  960. if ($Response == FALSE)
  961. $Response = curl_error($Handler);
  962. curl_close($Handler);
  963. } else if (function_exists('fsockopen')) {
  964. $Referer = Gdn::Request()->WebRoot();
  965. // Make the request
  966. $Pointer = @fsockopen($Host, $Port, $ErrorNumber, $Error, $Timeout);
  967. if (!$Pointer)
  968. throw new Exception(sprintf(T('Encountered an error while making a request to the remote server (%1$s): [%2$s] %3$s'), $Url, $ErrorNumber, $Error));
  969. $Request = "HEAD $Path?$Query HTTP/1.1\r\n";
  970. $HostHeader = $Host.($Post != 80) ? ":{$Port}" : '';
  971. $Header = array(
  972. 'Host' => $HostHeader,
  973. 'User-Agent' => ArrayValue('HTTP_USER_AGENT', $_SERVER, 'Vanilla/2.0'),
  974. 'Accept' => '*/*',
  975. 'Accept-Charset' => 'utf-8',
  976. 'Referer' => $Referer,
  977. 'Connection' => 'close'
  978. );
  979. if (strlen($Cookie['Cookie']))
  980. $Header = array_merge($Header, $Cookie);
  981. $Header = array_merge($Header, $Headers);
  982. $HeaderString = "";
  983. foreach ($Header as $HeaderName => $HeaderValue) {
  984. $HeaderString .= "{$HeaderName}: {$HeaderValue}\r\n";
  985. }
  986. $HeaderString .= "\r\n";
  987. // Send the headers and get the response
  988. fputs($Pointer, $Request);
  989. fputs($Pointer, $HeaderString);
  990. while ($Line = fread($Pointer, 4096)) {
  991. $Response .= $Line;
  992. }
  993. @fclose($Pointer);
  994. $Response = trim($Response);
  995. } else {
  996. throw new Exception(T('Encountered an error while making a request to the remote server: Your PHP configuration does not allow curl or fsock requests.'));
  997. }
  998. $ResponseLines = explode("\n",trim($Response));
  999. $Status = array_shift($ResponseLines);
  1000. $Response = array();
  1001. $Response['HTTP'] = trim($Status);
  1002. /* get the numeric status code.
  1003. * - trim off excess edge whitespace,
  1004. * - split on spaces,
  1005. * - get the 2nd element (as a single element array),
  1006. * - pop the first (only) element off it...
  1007. * - return that.
  1008. */
  1009. $Response['StatusCode'] = array_pop(array_slice(explode(' ',trim($Status)),1,1));
  1010. foreach ($ResponseLines as $Line) {
  1011. $Line = explode(':',trim($Line));
  1012. $Key = trim(array_shift($Line));
  1013. $Value = trim(implode(':',$Line));
  1014. $Response[$Key] = $Value;
  1015. }
  1016. if ($FollowRedirects) {
  1017. $Code = GetValue('StatusCode',$Response, 200);
  1018. if (in_array($Code, array(301,302))) {
  1019. if (array_key_exists('Location', $Response)) {
  1020. $Location = GetValue('Location', $Response);
  1021. return ProxyHead($Location, $OriginalHeaders, $OriginalTimeout, $FollowRedirects);
  1022. }
  1023. }
  1024. }
  1025. return $Response;
  1026. }
  1027. }
  1028. if (!function_exists('ProxyRequest')) {
  1029. /**
  1030. * Uses curl or fsock to make a request to a remote server. Returns the
  1031. * response.
  1032. *
  1033. * @param string $Url The full url to the page being requested (including http://)
  1034. */
  1035. function ProxyRequest($Url, $Timeout = FALSE, $FollowRedirects = FALSE) {
  1036. $OriginalTimeout = $Timeout;
  1037. if(!$Timeout)
  1038. $Timeout = C('Garden.SocketTimeout', 1.0);
  1039. $UrlParts = parse_url($Url);
  1040. $Scheme = GetValue('scheme', $UrlParts, 'http');
  1041. $Host = GetValue('host', $UrlParts, '');
  1042. $Port = GetValue('port', $UrlParts, '80');
  1043. $Path = GetValue('path', $UrlParts, '');
  1044. $Query = GetValue('query', $UrlParts, '');
  1045. // Get the cookie.
  1046. $Cookie = '';
  1047. $EncodeCookies = C('Garden.Cookie.Urlencode',TRUE);
  1048. foreach($_COOKIE as $Key => $Value) {
  1049. if(strncasecmp($Key, 'XDEBUG', 6) == 0)
  1050. continue;
  1051. if(strlen($Cookie) > 0)
  1052. $Cookie .= '; ';
  1053. $EValue = ($EncodeCookies) ? urlencode($Value) : $Value;
  1054. $Cookie .= "{$Key}={$EValue}";
  1055. }
  1056. $Response = '';
  1057. if (function_exists('curl_init')) {
  1058. //$Url = $Scheme.'://'.$Host.$Path;
  1059. $Handler = curl_init();
  1060. curl_setopt($Handler, CURLOPT_URL, $Url);
  1061. curl_setopt($Handler, CURLOPT_PORT, $Port);
  1062. curl_setopt($Handler, CURLOPT_HEADER, 1);
  1063. curl_setopt($Handler, CURLOPT_USERAGENT, ArrayValue('HTTP_USER_AGENT', $_SERVER, 'Vanilla/2.0'));
  1064. curl_setopt($Handler, CURLOPT_RETURNTRANSFER, 1);
  1065. if ($Cookie != '')
  1066. curl_setopt($Handler, CURLOPT_COOKIE, $Cookie);
  1067. // TIM @ 2010-06-28: Commented this out because it was forcing all requests with parameters to be POST. Same for the $Url above
  1068. //
  1069. //if ($Query != '') {
  1070. // curl_setopt($Handler, CURLOPT_POST, 1);
  1071. // curl_setopt($Handler, CURLOPT_POSTFIELDS, $Query);
  1072. //}
  1073. $Response = curl_exec($Handler);
  1074. $Success = TRUE;
  1075. if ($Response == FALSE) {
  1076. $Success = FALSE;
  1077. $Response = curl_error($Handler);
  1078. }
  1079. curl_close($Handler);
  1080. } else if (function_exists('fsockopen')) {
  1081. $Referer = Gdn_Url::WebRoot(TRUE);
  1082. // Make the request
  1083. $Pointer = @fsockopen($Host, $Port, $ErrorNumber, $Error);
  1084. if (!$Pointer)
  1085. throw new Exception(sprintf(T('Encountered an error while making a request to the remote server (%1$s): [%2$s] %3$s'), $Url, $ErrorNumber, $Error));
  1086. if(strlen($Cookie) > 0)
  1087. $Cookie = "Cookie: $Cookie\r\n";
  1088. $HostHeader = $Host.(($Port != 80) ? ":{$Port}" : '');
  1089. $Header = "GET $Path?$Query HTTP/1.1\r\n"
  1090. ."Host: {$HostHeader}\r\n"
  1091. // If you've got basic authentication enabled for the app, you're going to need to explicitly define the user/pass for this fsock call
  1092. // "Authorization: Basic ". base64_encode ("username:password")."\r\n" .
  1093. ."User-Agent: ".ArrayValue('HTTP_USER_AGENT', $_SERVER, 'Vanilla/2.0')."\r\n"
  1094. ."Accept: */*\r\n"
  1095. ."Accept-Charset: utf-8;\r\n"
  1096. ."Referer: {$Referer}\r\n"
  1097. ."Connection: close\r\n";
  1098. if ($Cookie != '')
  1099. $Header .= $Cookie;
  1100. $Header .= "\r\n";
  1101. // Send the headers and get the response
  1102. fputs($Pointer, $Header);
  1103. while ($Line = fread($Pointer, 4096)) {
  1104. $Response .= $Line;
  1105. }
  1106. @fclose($Pointer);
  1107. $Response = trim(substr($Response, strpos($Response, "\r\n\r\n") + 4));
  1108. $Success = TRUE;
  1109. } else {
  1110. throw new Exception(T('Encountered an error while making a request to the remote server: Your PHP configuration does not allow curl or fsock requests.'));
  1111. }
  1112. if (!$Success)
  1113. return $Response;
  1114. $ResponseHeaderData = trim(substr($Response, 0, strpos($Response, "\r\n\r\n")));
  1115. $Response = trim(substr($Response, strpos($Response, "\r\n\r\n") + 4));
  1116. $ResponseHeaderLines = explode("\n",trim($ResponseHeaderData));
  1117. $Status = array_shift($ResponseHeaderLines);
  1118. $ResponseHeaders = array();
  1119. $ResponseHeaders['HTTP'] = trim($Status);
  1120. /* get the numeric status code.
  1121. * - trim off excess edge whitespace,
  1122. * - split on spaces,
  1123. * - get the 2nd element (as a single element array),
  1124. * - pop the first (only) element off it...
  1125. * - return that.
  1126. */
  1127. $ResponseHeaders['StatusCode'] = array_pop(array_slice(explode(' ',trim($Status)),1,1));
  1128. foreach ($ResponseHeaderLines as $Line) {
  1129. $Line = explode(':',trim($Line));
  1130. $Key = trim(array_shift($Line));
  1131. $Value = trim(implode(':',$Line));
  1132. $ResponseHeaders[$Key] = $Value;
  1133. }
  1134. if ($FollowRedirects) {
  1135. $Code = GetValue('StatusCode',$ResponseHeaders, 200);
  1136. if (in_array($Code, array(301,302))) {
  1137. if (array_key_exists('Location', $ResponseHeaders)) {
  1138. $Location = GetValue('Location', $ResponseHeaders);
  1139. return ProxyRequest($Location, $OriginalTimeout, $FollowRedirects);
  1140. }
  1141. }
  1142. }
  1143. return $Response;
  1144. }
  1145. }
  1146. if (!function_exists('RandomString')) {
  1147. function RandomString($Length, $Characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') {
  1148. $CharLen = strlen($Characters) - 1;
  1149. $String = '' ;
  1150. for ($i = 0; $i < $Length; ++$i) {
  1151. $Offset = rand() % $CharLen;
  1152. $String .= substr($Characters, $Offset, 1);
  1153. }
  1154. return $String;
  1155. }
  1156. }
  1157. if (!function_exists('Redirect')) {
  1158. function Redirect($Destination = FALSE, $StatusCode = NULL) {
  1159. if (!$Destination)
  1160. $Destination = Url('');
  1161. // Close any db connections before exit
  1162. $Database = Gdn::Database();
  1163. $Database->CloseConnection();
  1164. // Clear out any previously sent content
  1165. @ob_end_clean();
  1166. // assign status code
  1167. $SendCode = (is_null($StatusCode)) ? 302 : $StatusCode;
  1168. // re-assign the location header
  1169. header("location: ".Url($Destination), TRUE, $SendCode);
  1170. // Exit
  1171. exit();
  1172. }
  1173. }
  1174. if (!function_exists('RemoteIP')) {
  1175. function RemoteIP() {
  1176. return GetValue('REMOTE_ADDR', $_SERVER, 'undefined');
  1177. }
  1178. }
  1179. if (!function_exists('RemoveFromConfig')) {
  1180. function RemoveFromConfig($Name) {
  1181. $Config = Gdn::Factory(Gdn::AliasConfig);
  1182. $Path = PATH_CONF . DS . 'config.php';
  1183. $Config->Load($Path, 'Save');
  1184. if (!is_array($Name))
  1185. $Name = array($Name);
  1186. foreach ($Name as $k) {
  1187. $Config->Remove($k);
  1188. }
  1189. $Result = $Config->Save($Path);
  1190. if ($Result)
  1191. $Config->Load($Path, 'Use');
  1192. return $Result;
  1193. }
  1194. }
  1195. // Functions relating to data/variable types and type casting
  1196. if (!function_exists('RemoveKeyFromArray')) {
  1197. function RemoveKeyFromArray($Array, $Key) {
  1198. if (!is_array($Key))
  1199. $Key = array($Key);
  1200. $Count = count($Key);
  1201. for ($i = 0; $i < $Count; $i++) {
  1202. $KeyIndex = array_keys(array_keys($Array), $Key[$i]);
  1203. if (count($KeyIndex) > 0) array_splice($Array, $KeyIndex[0], 1);
  1204. }
  1205. return $Array;
  1206. }
  1207. }
  1208. if (!function_exists('RemoveQuoteSlashes')) {
  1209. function RemoveQuoteSlashes($String) {
  1210. return str_replace("\\\"", '"', $String);
  1211. }
  1212. }
  1213. if (!function_exists('SafeGlob')) {
  1214. function SafeGlob($Pattern, $Extensions = array()) {
  1215. $Result = glob($Pattern);
  1216. if (!is_array($Result))
  1217. $Result = array();
  1218. // Check against allowed extensions.
  1219. if (count($Extensions) > 0) {
  1220. foreach ($Result as $Index => $Path) {
  1221. if (!$Path)
  1222. continue;
  1223. if (!in_array(strtolower(pathinfo($Path, PATHINFO_EXTENSION)), $Extensions))
  1224. unset($Result[$Index]);
  1225. }
  1226. }
  1227. return $Result;
  1228. }
  1229. }
  1230. if (!function_exists('SafeParseStr')) {
  1231. function SafeParseStr($Str, &$Output, $Original = NULL) {
  1232. $Exploded = explode('&',$Str);
  1233. $Output = array();
  1234. if (is_array($Original)) {
  1235. $FirstValue = reset($Original);
  1236. $FirstKey = key($Original);
  1237. unset($Original[$FirstKey]);
  1238. }
  1239. foreach ($Exploded as $Parameter) {
  1240. $Parts = explode('=', $Parameter);
  1241. $Key = $Parts[0];
  1242. $Value = count($Parts) > 1 ? $Parts[1] : '';
  1243. if (!is_null($Original)) {
  1244. $Output[$Key] = $FirstValue;
  1245. $Output = array_merge($Output, $Original);
  1246. break;
  1247. }
  1248. $Output[$Key] = $Value;
  1249. }
  1250. }
  1251. }
  1252. if (!function_exists('SaveToConfig')) {
  1253. /**
  1254. * Save values to the application's configuration file.
  1255. *
  1256. * @param string|array $Name One of the following:
  1257. * - string: The key to save.
  1258. * - array: An array of key/value pairs to save.
  1259. * @param mixed|null $Value The value to save.
  1260. * @param array $Options An array of additional options for the save.
  1261. * - Save: If this is false then only the in-memory config is set.
  1262. * - RemoveEmpty: If this is true then empty/false values will be removed from the config.
  1263. * @return bool: Whether or not the save was successful. NULL if no changes were necessary.
  1264. */
  1265. function SaveToConfig($Name, $Value = '', $Options = array()) {
  1266. // Don't save the value if it hasn't changed.
  1267. /*
  1268. Tim: The world ain't ready for you yet, son
  1269. if (is_string($Name) && C($Name) == $Value)
  1270. return NULL;
  1271. */
  1272. $Save = $Options === FALSE ? FALSE : GetValue('Save', $Options, TRUE);
  1273. $RemoveEmpty = GetValue('RemoveEmpty', $Options);
  1274. $Config = Gdn::Factory(Gdn::AliasConfig);
  1275. $Path = PATH_CONF . DS . 'config.php';
  1276. $Config->Load($Path, 'Save');
  1277. if (!is_array($Name))
  1278. $Name = array($Name => $Value);
  1279. foreach ($Name as $k => $v) {
  1280. if (!$v && $RemoveEmpty) {
  1281. $Config->Remove($k);
  1282. } else {
  1283. $Config->Set($k, $v, TRUE, $Save);
  1284. }
  1285. }
  1286. if ($Save)
  1287. return $Config->Save($Path);
  1288. else
  1289. return TRUE;
  1290. }
  1291. }
  1292. if (!function_exists('SliceString')) {
  1293. function SliceString($String, $Length, $Suffix = '…') {
  1294. if (function_exists('mb_strimwidth')) {
  1295. static $Charset;
  1296. if(is_null($Charset)) $Charset = Gdn::Config('Garden.Charset', 'utf-8');
  1297. return mb_strimwidth($String, 0, $Length, $Suffix, $Charset);
  1298. }

Large files files are truncated, but you can click here to view the full file